15e3dd157SKalle Valo /* 25e3dd157SKalle Valo * Copyright (c) 2005-2011 Atheros Communications Inc. 35e3dd157SKalle Valo * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. 45e3dd157SKalle Valo * 55e3dd157SKalle Valo * Permission to use, copy, modify, and/or distribute this software for any 65e3dd157SKalle Valo * purpose with or without fee is hereby granted, provided that the above 75e3dd157SKalle Valo * copyright notice and this permission notice appear in all copies. 85e3dd157SKalle Valo * 95e3dd157SKalle Valo * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 105e3dd157SKalle Valo * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 115e3dd157SKalle Valo * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 125e3dd157SKalle Valo * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 135e3dd157SKalle Valo * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 145e3dd157SKalle Valo * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 155e3dd157SKalle Valo * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 165e3dd157SKalle Valo */ 175e3dd157SKalle Valo 185e3dd157SKalle Valo #include <linux/skbuff.h> 192fe5288cSKalle Valo #include <linux/ctype.h> 205e3dd157SKalle Valo 215e3dd157SKalle Valo #include "core.h" 225e3dd157SKalle Valo #include "htc.h" 235e3dd157SKalle Valo #include "debug.h" 245e3dd157SKalle Valo #include "wmi.h" 255e3dd157SKalle Valo #include "mac.h" 265e3dd157SKalle Valo 27ce42870eSBartosz Markowski /* MAIN WMI cmd track */ 28ce42870eSBartosz Markowski static struct wmi_cmd_map wmi_cmd_map = { 29ce42870eSBartosz Markowski .init_cmdid = WMI_INIT_CMDID, 30ce42870eSBartosz Markowski .start_scan_cmdid = WMI_START_SCAN_CMDID, 31ce42870eSBartosz Markowski .stop_scan_cmdid = WMI_STOP_SCAN_CMDID, 32ce42870eSBartosz Markowski .scan_chan_list_cmdid = WMI_SCAN_CHAN_LIST_CMDID, 33ce42870eSBartosz Markowski .scan_sch_prio_tbl_cmdid = WMI_SCAN_SCH_PRIO_TBL_CMDID, 34ce42870eSBartosz Markowski .pdev_set_regdomain_cmdid = WMI_PDEV_SET_REGDOMAIN_CMDID, 35ce42870eSBartosz Markowski .pdev_set_channel_cmdid = WMI_PDEV_SET_CHANNEL_CMDID, 36ce42870eSBartosz Markowski .pdev_set_param_cmdid = WMI_PDEV_SET_PARAM_CMDID, 37ce42870eSBartosz Markowski .pdev_pktlog_enable_cmdid = WMI_PDEV_PKTLOG_ENABLE_CMDID, 38ce42870eSBartosz Markowski .pdev_pktlog_disable_cmdid = WMI_PDEV_PKTLOG_DISABLE_CMDID, 39ce42870eSBartosz Markowski .pdev_set_wmm_params_cmdid = WMI_PDEV_SET_WMM_PARAMS_CMDID, 40ce42870eSBartosz Markowski .pdev_set_ht_cap_ie_cmdid = WMI_PDEV_SET_HT_CAP_IE_CMDID, 41ce42870eSBartosz Markowski .pdev_set_vht_cap_ie_cmdid = WMI_PDEV_SET_VHT_CAP_IE_CMDID, 42ce42870eSBartosz Markowski .pdev_set_dscp_tid_map_cmdid = WMI_PDEV_SET_DSCP_TID_MAP_CMDID, 43ce42870eSBartosz Markowski .pdev_set_quiet_mode_cmdid = WMI_PDEV_SET_QUIET_MODE_CMDID, 44ce42870eSBartosz Markowski .pdev_green_ap_ps_enable_cmdid = WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID, 45ce42870eSBartosz Markowski .pdev_get_tpc_config_cmdid = WMI_PDEV_GET_TPC_CONFIG_CMDID, 46ce42870eSBartosz Markowski .pdev_set_base_macaddr_cmdid = WMI_PDEV_SET_BASE_MACADDR_CMDID, 47ce42870eSBartosz Markowski .vdev_create_cmdid = WMI_VDEV_CREATE_CMDID, 48ce42870eSBartosz Markowski .vdev_delete_cmdid = WMI_VDEV_DELETE_CMDID, 49ce42870eSBartosz Markowski .vdev_start_request_cmdid = WMI_VDEV_START_REQUEST_CMDID, 50ce42870eSBartosz Markowski .vdev_restart_request_cmdid = WMI_VDEV_RESTART_REQUEST_CMDID, 51ce42870eSBartosz Markowski .vdev_up_cmdid = WMI_VDEV_UP_CMDID, 52ce42870eSBartosz Markowski .vdev_stop_cmdid = WMI_VDEV_STOP_CMDID, 53ce42870eSBartosz Markowski .vdev_down_cmdid = WMI_VDEV_DOWN_CMDID, 54ce42870eSBartosz Markowski .vdev_set_param_cmdid = WMI_VDEV_SET_PARAM_CMDID, 55ce42870eSBartosz Markowski .vdev_install_key_cmdid = WMI_VDEV_INSTALL_KEY_CMDID, 56ce42870eSBartosz Markowski .peer_create_cmdid = WMI_PEER_CREATE_CMDID, 57ce42870eSBartosz Markowski .peer_delete_cmdid = WMI_PEER_DELETE_CMDID, 58ce42870eSBartosz Markowski .peer_flush_tids_cmdid = WMI_PEER_FLUSH_TIDS_CMDID, 59ce42870eSBartosz Markowski .peer_set_param_cmdid = WMI_PEER_SET_PARAM_CMDID, 60ce42870eSBartosz Markowski .peer_assoc_cmdid = WMI_PEER_ASSOC_CMDID, 61ce42870eSBartosz Markowski .peer_add_wds_entry_cmdid = WMI_PEER_ADD_WDS_ENTRY_CMDID, 62ce42870eSBartosz Markowski .peer_remove_wds_entry_cmdid = WMI_PEER_REMOVE_WDS_ENTRY_CMDID, 63ce42870eSBartosz Markowski .peer_mcast_group_cmdid = WMI_PEER_MCAST_GROUP_CMDID, 64ce42870eSBartosz Markowski .bcn_tx_cmdid = WMI_BCN_TX_CMDID, 65ce42870eSBartosz Markowski .pdev_send_bcn_cmdid = WMI_PDEV_SEND_BCN_CMDID, 66ce42870eSBartosz Markowski .bcn_tmpl_cmdid = WMI_BCN_TMPL_CMDID, 67ce42870eSBartosz Markowski .bcn_filter_rx_cmdid = WMI_BCN_FILTER_RX_CMDID, 68ce42870eSBartosz Markowski .prb_req_filter_rx_cmdid = WMI_PRB_REQ_FILTER_RX_CMDID, 69ce42870eSBartosz Markowski .mgmt_tx_cmdid = WMI_MGMT_TX_CMDID, 70ce42870eSBartosz Markowski .prb_tmpl_cmdid = WMI_PRB_TMPL_CMDID, 71ce42870eSBartosz Markowski .addba_clear_resp_cmdid = WMI_ADDBA_CLEAR_RESP_CMDID, 72ce42870eSBartosz Markowski .addba_send_cmdid = WMI_ADDBA_SEND_CMDID, 73ce42870eSBartosz Markowski .addba_status_cmdid = WMI_ADDBA_STATUS_CMDID, 74ce42870eSBartosz Markowski .delba_send_cmdid = WMI_DELBA_SEND_CMDID, 75ce42870eSBartosz Markowski .addba_set_resp_cmdid = WMI_ADDBA_SET_RESP_CMDID, 76ce42870eSBartosz Markowski .send_singleamsdu_cmdid = WMI_SEND_SINGLEAMSDU_CMDID, 77ce42870eSBartosz Markowski .sta_powersave_mode_cmdid = WMI_STA_POWERSAVE_MODE_CMDID, 78ce42870eSBartosz Markowski .sta_powersave_param_cmdid = WMI_STA_POWERSAVE_PARAM_CMDID, 79ce42870eSBartosz Markowski .sta_mimo_ps_mode_cmdid = WMI_STA_MIMO_PS_MODE_CMDID, 80ce42870eSBartosz Markowski .pdev_dfs_enable_cmdid = WMI_PDEV_DFS_ENABLE_CMDID, 81ce42870eSBartosz Markowski .pdev_dfs_disable_cmdid = WMI_PDEV_DFS_DISABLE_CMDID, 82ce42870eSBartosz Markowski .roam_scan_mode = WMI_ROAM_SCAN_MODE, 83ce42870eSBartosz Markowski .roam_scan_rssi_threshold = WMI_ROAM_SCAN_RSSI_THRESHOLD, 84ce42870eSBartosz Markowski .roam_scan_period = WMI_ROAM_SCAN_PERIOD, 85ce42870eSBartosz Markowski .roam_scan_rssi_change_threshold = WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD, 86ce42870eSBartosz Markowski .roam_ap_profile = WMI_ROAM_AP_PROFILE, 87ce42870eSBartosz Markowski .ofl_scan_add_ap_profile = WMI_ROAM_AP_PROFILE, 88ce42870eSBartosz Markowski .ofl_scan_remove_ap_profile = WMI_OFL_SCAN_REMOVE_AP_PROFILE, 89ce42870eSBartosz Markowski .ofl_scan_period = WMI_OFL_SCAN_PERIOD, 90ce42870eSBartosz Markowski .p2p_dev_set_device_info = WMI_P2P_DEV_SET_DEVICE_INFO, 91ce42870eSBartosz Markowski .p2p_dev_set_discoverability = WMI_P2P_DEV_SET_DISCOVERABILITY, 92ce42870eSBartosz Markowski .p2p_go_set_beacon_ie = WMI_P2P_GO_SET_BEACON_IE, 93ce42870eSBartosz Markowski .p2p_go_set_probe_resp_ie = WMI_P2P_GO_SET_PROBE_RESP_IE, 94ce42870eSBartosz Markowski .p2p_set_vendor_ie_data_cmdid = WMI_P2P_SET_VENDOR_IE_DATA_CMDID, 95ce42870eSBartosz Markowski .ap_ps_peer_param_cmdid = WMI_AP_PS_PEER_PARAM_CMDID, 96ce42870eSBartosz Markowski .ap_ps_peer_uapsd_coex_cmdid = WMI_AP_PS_PEER_UAPSD_COEX_CMDID, 97ce42870eSBartosz Markowski .peer_rate_retry_sched_cmdid = WMI_PEER_RATE_RETRY_SCHED_CMDID, 98ce42870eSBartosz Markowski .wlan_profile_trigger_cmdid = WMI_WLAN_PROFILE_TRIGGER_CMDID, 99ce42870eSBartosz Markowski .wlan_profile_set_hist_intvl_cmdid = 100ce42870eSBartosz Markowski WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, 101ce42870eSBartosz Markowski .wlan_profile_get_profile_data_cmdid = 102ce42870eSBartosz Markowski WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, 103ce42870eSBartosz Markowski .wlan_profile_enable_profile_id_cmdid = 104ce42870eSBartosz Markowski WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, 105ce42870eSBartosz Markowski .wlan_profile_list_profile_id_cmdid = 106ce42870eSBartosz Markowski WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, 107ce42870eSBartosz Markowski .pdev_suspend_cmdid = WMI_PDEV_SUSPEND_CMDID, 108ce42870eSBartosz Markowski .pdev_resume_cmdid = WMI_PDEV_RESUME_CMDID, 109ce42870eSBartosz Markowski .add_bcn_filter_cmdid = WMI_ADD_BCN_FILTER_CMDID, 110ce42870eSBartosz Markowski .rmv_bcn_filter_cmdid = WMI_RMV_BCN_FILTER_CMDID, 111ce42870eSBartosz Markowski .wow_add_wake_pattern_cmdid = WMI_WOW_ADD_WAKE_PATTERN_CMDID, 112ce42870eSBartosz Markowski .wow_del_wake_pattern_cmdid = WMI_WOW_DEL_WAKE_PATTERN_CMDID, 113ce42870eSBartosz Markowski .wow_enable_disable_wake_event_cmdid = 114ce42870eSBartosz Markowski WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, 115ce42870eSBartosz Markowski .wow_enable_cmdid = WMI_WOW_ENABLE_CMDID, 116ce42870eSBartosz Markowski .wow_hostwakeup_from_sleep_cmdid = WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, 117ce42870eSBartosz Markowski .rtt_measreq_cmdid = WMI_RTT_MEASREQ_CMDID, 118ce42870eSBartosz Markowski .rtt_tsf_cmdid = WMI_RTT_TSF_CMDID, 119ce42870eSBartosz Markowski .vdev_spectral_scan_configure_cmdid = 120ce42870eSBartosz Markowski WMI_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID, 121ce42870eSBartosz Markowski .vdev_spectral_scan_enable_cmdid = WMI_VDEV_SPECTRAL_SCAN_ENABLE_CMDID, 122ce42870eSBartosz Markowski .request_stats_cmdid = WMI_REQUEST_STATS_CMDID, 123ce42870eSBartosz Markowski .set_arp_ns_offload_cmdid = WMI_SET_ARP_NS_OFFLOAD_CMDID, 124ce42870eSBartosz Markowski .network_list_offload_config_cmdid = 125ce42870eSBartosz Markowski WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID, 126ce42870eSBartosz Markowski .gtk_offload_cmdid = WMI_GTK_OFFLOAD_CMDID, 127ce42870eSBartosz Markowski .csa_offload_enable_cmdid = WMI_CSA_OFFLOAD_ENABLE_CMDID, 128ce42870eSBartosz Markowski .csa_offload_chanswitch_cmdid = WMI_CSA_OFFLOAD_CHANSWITCH_CMDID, 129ce42870eSBartosz Markowski .chatter_set_mode_cmdid = WMI_CHATTER_SET_MODE_CMDID, 130ce42870eSBartosz Markowski .peer_tid_addba_cmdid = WMI_PEER_TID_ADDBA_CMDID, 131ce42870eSBartosz Markowski .peer_tid_delba_cmdid = WMI_PEER_TID_DELBA_CMDID, 132ce42870eSBartosz Markowski .sta_dtim_ps_method_cmdid = WMI_STA_DTIM_PS_METHOD_CMDID, 133ce42870eSBartosz Markowski .sta_uapsd_auto_trig_cmdid = WMI_STA_UAPSD_AUTO_TRIG_CMDID, 134ce42870eSBartosz Markowski .sta_keepalive_cmd = WMI_STA_KEEPALIVE_CMD, 135ce42870eSBartosz Markowski .echo_cmdid = WMI_ECHO_CMDID, 136ce42870eSBartosz Markowski .pdev_utf_cmdid = WMI_PDEV_UTF_CMDID, 137ce42870eSBartosz Markowski .dbglog_cfg_cmdid = WMI_DBGLOG_CFG_CMDID, 138ce42870eSBartosz Markowski .pdev_qvit_cmdid = WMI_PDEV_QVIT_CMDID, 139ce42870eSBartosz Markowski .pdev_ftm_intg_cmdid = WMI_PDEV_FTM_INTG_CMDID, 140ce42870eSBartosz Markowski .vdev_set_keepalive_cmdid = WMI_VDEV_SET_KEEPALIVE_CMDID, 141ce42870eSBartosz Markowski .vdev_get_keepalive_cmdid = WMI_VDEV_GET_KEEPALIVE_CMDID, 142ce42870eSBartosz Markowski .force_fw_hang_cmdid = WMI_FORCE_FW_HANG_CMDID, 143ce42870eSBartosz Markowski .gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID, 144ce42870eSBartosz Markowski .gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID, 145ce42870eSBartosz Markowski }; 146ce42870eSBartosz Markowski 147b7e3adf9SBartosz Markowski /* 10.X WMI cmd track */ 148b7e3adf9SBartosz Markowski static struct wmi_cmd_map wmi_10x_cmd_map = { 149b7e3adf9SBartosz Markowski .init_cmdid = WMI_10X_INIT_CMDID, 150b7e3adf9SBartosz Markowski .start_scan_cmdid = WMI_10X_START_SCAN_CMDID, 151b7e3adf9SBartosz Markowski .stop_scan_cmdid = WMI_10X_STOP_SCAN_CMDID, 152b7e3adf9SBartosz Markowski .scan_chan_list_cmdid = WMI_10X_SCAN_CHAN_LIST_CMDID, 15334957b25SBartosz Markowski .scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED, 154b7e3adf9SBartosz Markowski .pdev_set_regdomain_cmdid = WMI_10X_PDEV_SET_REGDOMAIN_CMDID, 155b7e3adf9SBartosz Markowski .pdev_set_channel_cmdid = WMI_10X_PDEV_SET_CHANNEL_CMDID, 156b7e3adf9SBartosz Markowski .pdev_set_param_cmdid = WMI_10X_PDEV_SET_PARAM_CMDID, 157b7e3adf9SBartosz Markowski .pdev_pktlog_enable_cmdid = WMI_10X_PDEV_PKTLOG_ENABLE_CMDID, 158b7e3adf9SBartosz Markowski .pdev_pktlog_disable_cmdid = WMI_10X_PDEV_PKTLOG_DISABLE_CMDID, 159b7e3adf9SBartosz Markowski .pdev_set_wmm_params_cmdid = WMI_10X_PDEV_SET_WMM_PARAMS_CMDID, 160b7e3adf9SBartosz Markowski .pdev_set_ht_cap_ie_cmdid = WMI_10X_PDEV_SET_HT_CAP_IE_CMDID, 161b7e3adf9SBartosz Markowski .pdev_set_vht_cap_ie_cmdid = WMI_10X_PDEV_SET_VHT_CAP_IE_CMDID, 162b7e3adf9SBartosz Markowski .pdev_set_dscp_tid_map_cmdid = WMI_10X_PDEV_SET_DSCP_TID_MAP_CMDID, 163b7e3adf9SBartosz Markowski .pdev_set_quiet_mode_cmdid = WMI_10X_PDEV_SET_QUIET_MODE_CMDID, 164b7e3adf9SBartosz Markowski .pdev_green_ap_ps_enable_cmdid = WMI_10X_PDEV_GREEN_AP_PS_ENABLE_CMDID, 165b7e3adf9SBartosz Markowski .pdev_get_tpc_config_cmdid = WMI_10X_PDEV_GET_TPC_CONFIG_CMDID, 166b7e3adf9SBartosz Markowski .pdev_set_base_macaddr_cmdid = WMI_10X_PDEV_SET_BASE_MACADDR_CMDID, 167b7e3adf9SBartosz Markowski .vdev_create_cmdid = WMI_10X_VDEV_CREATE_CMDID, 168b7e3adf9SBartosz Markowski .vdev_delete_cmdid = WMI_10X_VDEV_DELETE_CMDID, 169b7e3adf9SBartosz Markowski .vdev_start_request_cmdid = WMI_10X_VDEV_START_REQUEST_CMDID, 170b7e3adf9SBartosz Markowski .vdev_restart_request_cmdid = WMI_10X_VDEV_RESTART_REQUEST_CMDID, 171b7e3adf9SBartosz Markowski .vdev_up_cmdid = WMI_10X_VDEV_UP_CMDID, 172b7e3adf9SBartosz Markowski .vdev_stop_cmdid = WMI_10X_VDEV_STOP_CMDID, 173b7e3adf9SBartosz Markowski .vdev_down_cmdid = WMI_10X_VDEV_DOWN_CMDID, 174b7e3adf9SBartosz Markowski .vdev_set_param_cmdid = WMI_10X_VDEV_SET_PARAM_CMDID, 175b7e3adf9SBartosz Markowski .vdev_install_key_cmdid = WMI_10X_VDEV_INSTALL_KEY_CMDID, 176b7e3adf9SBartosz Markowski .peer_create_cmdid = WMI_10X_PEER_CREATE_CMDID, 177b7e3adf9SBartosz Markowski .peer_delete_cmdid = WMI_10X_PEER_DELETE_CMDID, 178b7e3adf9SBartosz Markowski .peer_flush_tids_cmdid = WMI_10X_PEER_FLUSH_TIDS_CMDID, 179b7e3adf9SBartosz Markowski .peer_set_param_cmdid = WMI_10X_PEER_SET_PARAM_CMDID, 180b7e3adf9SBartosz Markowski .peer_assoc_cmdid = WMI_10X_PEER_ASSOC_CMDID, 181b7e3adf9SBartosz Markowski .peer_add_wds_entry_cmdid = WMI_10X_PEER_ADD_WDS_ENTRY_CMDID, 182b7e3adf9SBartosz Markowski .peer_remove_wds_entry_cmdid = WMI_10X_PEER_REMOVE_WDS_ENTRY_CMDID, 183b7e3adf9SBartosz Markowski .peer_mcast_group_cmdid = WMI_10X_PEER_MCAST_GROUP_CMDID, 184b7e3adf9SBartosz Markowski .bcn_tx_cmdid = WMI_10X_BCN_TX_CMDID, 185b7e3adf9SBartosz Markowski .pdev_send_bcn_cmdid = WMI_10X_PDEV_SEND_BCN_CMDID, 18634957b25SBartosz Markowski .bcn_tmpl_cmdid = WMI_CMD_UNSUPPORTED, 187b7e3adf9SBartosz Markowski .bcn_filter_rx_cmdid = WMI_10X_BCN_FILTER_RX_CMDID, 188b7e3adf9SBartosz Markowski .prb_req_filter_rx_cmdid = WMI_10X_PRB_REQ_FILTER_RX_CMDID, 189b7e3adf9SBartosz Markowski .mgmt_tx_cmdid = WMI_10X_MGMT_TX_CMDID, 19034957b25SBartosz Markowski .prb_tmpl_cmdid = WMI_CMD_UNSUPPORTED, 191b7e3adf9SBartosz Markowski .addba_clear_resp_cmdid = WMI_10X_ADDBA_CLEAR_RESP_CMDID, 192b7e3adf9SBartosz Markowski .addba_send_cmdid = WMI_10X_ADDBA_SEND_CMDID, 193b7e3adf9SBartosz Markowski .addba_status_cmdid = WMI_10X_ADDBA_STATUS_CMDID, 194b7e3adf9SBartosz Markowski .delba_send_cmdid = WMI_10X_DELBA_SEND_CMDID, 195b7e3adf9SBartosz Markowski .addba_set_resp_cmdid = WMI_10X_ADDBA_SET_RESP_CMDID, 196b7e3adf9SBartosz Markowski .send_singleamsdu_cmdid = WMI_10X_SEND_SINGLEAMSDU_CMDID, 197b7e3adf9SBartosz Markowski .sta_powersave_mode_cmdid = WMI_10X_STA_POWERSAVE_MODE_CMDID, 198b7e3adf9SBartosz Markowski .sta_powersave_param_cmdid = WMI_10X_STA_POWERSAVE_PARAM_CMDID, 199b7e3adf9SBartosz Markowski .sta_mimo_ps_mode_cmdid = WMI_10X_STA_MIMO_PS_MODE_CMDID, 200b7e3adf9SBartosz Markowski .pdev_dfs_enable_cmdid = WMI_10X_PDEV_DFS_ENABLE_CMDID, 201b7e3adf9SBartosz Markowski .pdev_dfs_disable_cmdid = WMI_10X_PDEV_DFS_DISABLE_CMDID, 202b7e3adf9SBartosz Markowski .roam_scan_mode = WMI_10X_ROAM_SCAN_MODE, 203b7e3adf9SBartosz Markowski .roam_scan_rssi_threshold = WMI_10X_ROAM_SCAN_RSSI_THRESHOLD, 204b7e3adf9SBartosz Markowski .roam_scan_period = WMI_10X_ROAM_SCAN_PERIOD, 205b7e3adf9SBartosz Markowski .roam_scan_rssi_change_threshold = 206b7e3adf9SBartosz Markowski WMI_10X_ROAM_SCAN_RSSI_CHANGE_THRESHOLD, 207b7e3adf9SBartosz Markowski .roam_ap_profile = WMI_10X_ROAM_AP_PROFILE, 208b7e3adf9SBartosz Markowski .ofl_scan_add_ap_profile = WMI_10X_OFL_SCAN_ADD_AP_PROFILE, 209b7e3adf9SBartosz Markowski .ofl_scan_remove_ap_profile = WMI_10X_OFL_SCAN_REMOVE_AP_PROFILE, 210b7e3adf9SBartosz Markowski .ofl_scan_period = WMI_10X_OFL_SCAN_PERIOD, 211b7e3adf9SBartosz Markowski .p2p_dev_set_device_info = WMI_10X_P2P_DEV_SET_DEVICE_INFO, 212b7e3adf9SBartosz Markowski .p2p_dev_set_discoverability = WMI_10X_P2P_DEV_SET_DISCOVERABILITY, 213b7e3adf9SBartosz Markowski .p2p_go_set_beacon_ie = WMI_10X_P2P_GO_SET_BEACON_IE, 214b7e3adf9SBartosz Markowski .p2p_go_set_probe_resp_ie = WMI_10X_P2P_GO_SET_PROBE_RESP_IE, 21534957b25SBartosz Markowski .p2p_set_vendor_ie_data_cmdid = WMI_CMD_UNSUPPORTED, 216542fb174SJanusz Dziedzic .ap_ps_peer_param_cmdid = WMI_10X_AP_PS_PEER_PARAM_CMDID, 21734957b25SBartosz Markowski .ap_ps_peer_uapsd_coex_cmdid = WMI_CMD_UNSUPPORTED, 218b7e3adf9SBartosz Markowski .peer_rate_retry_sched_cmdid = WMI_10X_PEER_RATE_RETRY_SCHED_CMDID, 219b7e3adf9SBartosz Markowski .wlan_profile_trigger_cmdid = WMI_10X_WLAN_PROFILE_TRIGGER_CMDID, 220b7e3adf9SBartosz Markowski .wlan_profile_set_hist_intvl_cmdid = 221b7e3adf9SBartosz Markowski WMI_10X_WLAN_PROFILE_SET_HIST_INTVL_CMDID, 222b7e3adf9SBartosz Markowski .wlan_profile_get_profile_data_cmdid = 223b7e3adf9SBartosz Markowski WMI_10X_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, 224b7e3adf9SBartosz Markowski .wlan_profile_enable_profile_id_cmdid = 225b7e3adf9SBartosz Markowski WMI_10X_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, 226b7e3adf9SBartosz Markowski .wlan_profile_list_profile_id_cmdid = 227b7e3adf9SBartosz Markowski WMI_10X_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, 228b7e3adf9SBartosz Markowski .pdev_suspend_cmdid = WMI_10X_PDEV_SUSPEND_CMDID, 229b7e3adf9SBartosz Markowski .pdev_resume_cmdid = WMI_10X_PDEV_RESUME_CMDID, 230b7e3adf9SBartosz Markowski .add_bcn_filter_cmdid = WMI_10X_ADD_BCN_FILTER_CMDID, 231b7e3adf9SBartosz Markowski .rmv_bcn_filter_cmdid = WMI_10X_RMV_BCN_FILTER_CMDID, 232b7e3adf9SBartosz Markowski .wow_add_wake_pattern_cmdid = WMI_10X_WOW_ADD_WAKE_PATTERN_CMDID, 233b7e3adf9SBartosz Markowski .wow_del_wake_pattern_cmdid = WMI_10X_WOW_DEL_WAKE_PATTERN_CMDID, 234b7e3adf9SBartosz Markowski .wow_enable_disable_wake_event_cmdid = 235b7e3adf9SBartosz Markowski WMI_10X_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, 236b7e3adf9SBartosz Markowski .wow_enable_cmdid = WMI_10X_WOW_ENABLE_CMDID, 237b7e3adf9SBartosz Markowski .wow_hostwakeup_from_sleep_cmdid = 238b7e3adf9SBartosz Markowski WMI_10X_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, 239b7e3adf9SBartosz Markowski .rtt_measreq_cmdid = WMI_10X_RTT_MEASREQ_CMDID, 240b7e3adf9SBartosz Markowski .rtt_tsf_cmdid = WMI_10X_RTT_TSF_CMDID, 241b7e3adf9SBartosz Markowski .vdev_spectral_scan_configure_cmdid = 242b7e3adf9SBartosz Markowski WMI_10X_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID, 243b7e3adf9SBartosz Markowski .vdev_spectral_scan_enable_cmdid = 244b7e3adf9SBartosz Markowski WMI_10X_VDEV_SPECTRAL_SCAN_ENABLE_CMDID, 245b7e3adf9SBartosz Markowski .request_stats_cmdid = WMI_10X_REQUEST_STATS_CMDID, 24634957b25SBartosz Markowski .set_arp_ns_offload_cmdid = WMI_CMD_UNSUPPORTED, 24734957b25SBartosz Markowski .network_list_offload_config_cmdid = WMI_CMD_UNSUPPORTED, 24834957b25SBartosz Markowski .gtk_offload_cmdid = WMI_CMD_UNSUPPORTED, 24934957b25SBartosz Markowski .csa_offload_enable_cmdid = WMI_CMD_UNSUPPORTED, 25034957b25SBartosz Markowski .csa_offload_chanswitch_cmdid = WMI_CMD_UNSUPPORTED, 25134957b25SBartosz Markowski .chatter_set_mode_cmdid = WMI_CMD_UNSUPPORTED, 25234957b25SBartosz Markowski .peer_tid_addba_cmdid = WMI_CMD_UNSUPPORTED, 25334957b25SBartosz Markowski .peer_tid_delba_cmdid = WMI_CMD_UNSUPPORTED, 25434957b25SBartosz Markowski .sta_dtim_ps_method_cmdid = WMI_CMD_UNSUPPORTED, 25534957b25SBartosz Markowski .sta_uapsd_auto_trig_cmdid = WMI_CMD_UNSUPPORTED, 25634957b25SBartosz Markowski .sta_keepalive_cmd = WMI_CMD_UNSUPPORTED, 257b7e3adf9SBartosz Markowski .echo_cmdid = WMI_10X_ECHO_CMDID, 258b7e3adf9SBartosz Markowski .pdev_utf_cmdid = WMI_10X_PDEV_UTF_CMDID, 259b7e3adf9SBartosz Markowski .dbglog_cfg_cmdid = WMI_10X_DBGLOG_CFG_CMDID, 260b7e3adf9SBartosz Markowski .pdev_qvit_cmdid = WMI_10X_PDEV_QVIT_CMDID, 26134957b25SBartosz Markowski .pdev_ftm_intg_cmdid = WMI_CMD_UNSUPPORTED, 26234957b25SBartosz Markowski .vdev_set_keepalive_cmdid = WMI_CMD_UNSUPPORTED, 26334957b25SBartosz Markowski .vdev_get_keepalive_cmdid = WMI_CMD_UNSUPPORTED, 26434957b25SBartosz Markowski .force_fw_hang_cmdid = WMI_CMD_UNSUPPORTED, 265b7e3adf9SBartosz Markowski .gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID, 266b7e3adf9SBartosz Markowski .gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID, 267b7e3adf9SBartosz Markowski }; 268ce42870eSBartosz Markowski 2696d1506e7SBartosz Markowski /* MAIN WMI VDEV param map */ 2706d1506e7SBartosz Markowski static struct wmi_vdev_param_map wmi_vdev_param_map = { 2716d1506e7SBartosz Markowski .rts_threshold = WMI_VDEV_PARAM_RTS_THRESHOLD, 2726d1506e7SBartosz Markowski .fragmentation_threshold = WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD, 2736d1506e7SBartosz Markowski .beacon_interval = WMI_VDEV_PARAM_BEACON_INTERVAL, 2746d1506e7SBartosz Markowski .listen_interval = WMI_VDEV_PARAM_LISTEN_INTERVAL, 2756d1506e7SBartosz Markowski .multicast_rate = WMI_VDEV_PARAM_MULTICAST_RATE, 2766d1506e7SBartosz Markowski .mgmt_tx_rate = WMI_VDEV_PARAM_MGMT_TX_RATE, 2776d1506e7SBartosz Markowski .slot_time = WMI_VDEV_PARAM_SLOT_TIME, 2786d1506e7SBartosz Markowski .preamble = WMI_VDEV_PARAM_PREAMBLE, 2796d1506e7SBartosz Markowski .swba_time = WMI_VDEV_PARAM_SWBA_TIME, 2806d1506e7SBartosz Markowski .wmi_vdev_stats_update_period = WMI_VDEV_STATS_UPDATE_PERIOD, 2816d1506e7SBartosz Markowski .wmi_vdev_pwrsave_ageout_time = WMI_VDEV_PWRSAVE_AGEOUT_TIME, 2826d1506e7SBartosz Markowski .wmi_vdev_host_swba_interval = WMI_VDEV_HOST_SWBA_INTERVAL, 2836d1506e7SBartosz Markowski .dtim_period = WMI_VDEV_PARAM_DTIM_PERIOD, 2846d1506e7SBartosz Markowski .wmi_vdev_oc_scheduler_air_time_limit = 2856d1506e7SBartosz Markowski WMI_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, 2866d1506e7SBartosz Markowski .wds = WMI_VDEV_PARAM_WDS, 2876d1506e7SBartosz Markowski .atim_window = WMI_VDEV_PARAM_ATIM_WINDOW, 2886d1506e7SBartosz Markowski .bmiss_count_max = WMI_VDEV_PARAM_BMISS_COUNT_MAX, 2896d1506e7SBartosz Markowski .bmiss_first_bcnt = WMI_VDEV_PARAM_BMISS_FIRST_BCNT, 2906d1506e7SBartosz Markowski .bmiss_final_bcnt = WMI_VDEV_PARAM_BMISS_FINAL_BCNT, 2916d1506e7SBartosz Markowski .feature_wmm = WMI_VDEV_PARAM_FEATURE_WMM, 2926d1506e7SBartosz Markowski .chwidth = WMI_VDEV_PARAM_CHWIDTH, 2936d1506e7SBartosz Markowski .chextoffset = WMI_VDEV_PARAM_CHEXTOFFSET, 2946d1506e7SBartosz Markowski .disable_htprotection = WMI_VDEV_PARAM_DISABLE_HTPROTECTION, 2956d1506e7SBartosz Markowski .sta_quickkickout = WMI_VDEV_PARAM_STA_QUICKKICKOUT, 2966d1506e7SBartosz Markowski .mgmt_rate = WMI_VDEV_PARAM_MGMT_RATE, 2976d1506e7SBartosz Markowski .protection_mode = WMI_VDEV_PARAM_PROTECTION_MODE, 2986d1506e7SBartosz Markowski .fixed_rate = WMI_VDEV_PARAM_FIXED_RATE, 2996d1506e7SBartosz Markowski .sgi = WMI_VDEV_PARAM_SGI, 3006d1506e7SBartosz Markowski .ldpc = WMI_VDEV_PARAM_LDPC, 3016d1506e7SBartosz Markowski .tx_stbc = WMI_VDEV_PARAM_TX_STBC, 3026d1506e7SBartosz Markowski .rx_stbc = WMI_VDEV_PARAM_RX_STBC, 3036d1506e7SBartosz Markowski .intra_bss_fwd = WMI_VDEV_PARAM_INTRA_BSS_FWD, 3046d1506e7SBartosz Markowski .def_keyid = WMI_VDEV_PARAM_DEF_KEYID, 3056d1506e7SBartosz Markowski .nss = WMI_VDEV_PARAM_NSS, 3066d1506e7SBartosz Markowski .bcast_data_rate = WMI_VDEV_PARAM_BCAST_DATA_RATE, 3076d1506e7SBartosz Markowski .mcast_data_rate = WMI_VDEV_PARAM_MCAST_DATA_RATE, 3086d1506e7SBartosz Markowski .mcast_indicate = WMI_VDEV_PARAM_MCAST_INDICATE, 3096d1506e7SBartosz Markowski .dhcp_indicate = WMI_VDEV_PARAM_DHCP_INDICATE, 3106d1506e7SBartosz Markowski .unknown_dest_indicate = WMI_VDEV_PARAM_UNKNOWN_DEST_INDICATE, 3116d1506e7SBartosz Markowski .ap_keepalive_min_idle_inactive_time_secs = 3126d1506e7SBartosz Markowski WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, 3136d1506e7SBartosz Markowski .ap_keepalive_max_idle_inactive_time_secs = 3146d1506e7SBartosz Markowski WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, 3156d1506e7SBartosz Markowski .ap_keepalive_max_unresponsive_time_secs = 3166d1506e7SBartosz Markowski WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, 3176d1506e7SBartosz Markowski .ap_enable_nawds = WMI_VDEV_PARAM_AP_ENABLE_NAWDS, 3186d1506e7SBartosz Markowski .mcast2ucast_set = WMI_VDEV_PARAM_UNSUPPORTED, 3196d1506e7SBartosz Markowski .enable_rtscts = WMI_VDEV_PARAM_ENABLE_RTSCTS, 3206d1506e7SBartosz Markowski .txbf = WMI_VDEV_PARAM_TXBF, 3216d1506e7SBartosz Markowski .packet_powersave = WMI_VDEV_PARAM_PACKET_POWERSAVE, 3226d1506e7SBartosz Markowski .drop_unencry = WMI_VDEV_PARAM_DROP_UNENCRY, 3236d1506e7SBartosz Markowski .tx_encap_type = WMI_VDEV_PARAM_TX_ENCAP_TYPE, 3246d1506e7SBartosz Markowski .ap_detect_out_of_sync_sleeping_sta_time_secs = 3256d1506e7SBartosz Markowski WMI_VDEV_PARAM_UNSUPPORTED, 3266d1506e7SBartosz Markowski }; 3276d1506e7SBartosz Markowski 3286d1506e7SBartosz Markowski /* 10.X WMI VDEV param map */ 3296d1506e7SBartosz Markowski static struct wmi_vdev_param_map wmi_10x_vdev_param_map = { 3306d1506e7SBartosz Markowski .rts_threshold = WMI_10X_VDEV_PARAM_RTS_THRESHOLD, 3316d1506e7SBartosz Markowski .fragmentation_threshold = WMI_10X_VDEV_PARAM_FRAGMENTATION_THRESHOLD, 3326d1506e7SBartosz Markowski .beacon_interval = WMI_10X_VDEV_PARAM_BEACON_INTERVAL, 3336d1506e7SBartosz Markowski .listen_interval = WMI_10X_VDEV_PARAM_LISTEN_INTERVAL, 3346d1506e7SBartosz Markowski .multicast_rate = WMI_10X_VDEV_PARAM_MULTICAST_RATE, 3356d1506e7SBartosz Markowski .mgmt_tx_rate = WMI_10X_VDEV_PARAM_MGMT_TX_RATE, 3366d1506e7SBartosz Markowski .slot_time = WMI_10X_VDEV_PARAM_SLOT_TIME, 3376d1506e7SBartosz Markowski .preamble = WMI_10X_VDEV_PARAM_PREAMBLE, 3386d1506e7SBartosz Markowski .swba_time = WMI_10X_VDEV_PARAM_SWBA_TIME, 3396d1506e7SBartosz Markowski .wmi_vdev_stats_update_period = WMI_10X_VDEV_STATS_UPDATE_PERIOD, 3406d1506e7SBartosz Markowski .wmi_vdev_pwrsave_ageout_time = WMI_10X_VDEV_PWRSAVE_AGEOUT_TIME, 3416d1506e7SBartosz Markowski .wmi_vdev_host_swba_interval = WMI_10X_VDEV_HOST_SWBA_INTERVAL, 3426d1506e7SBartosz Markowski .dtim_period = WMI_10X_VDEV_PARAM_DTIM_PERIOD, 3436d1506e7SBartosz Markowski .wmi_vdev_oc_scheduler_air_time_limit = 3446d1506e7SBartosz Markowski WMI_10X_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, 3456d1506e7SBartosz Markowski .wds = WMI_10X_VDEV_PARAM_WDS, 3466d1506e7SBartosz Markowski .atim_window = WMI_10X_VDEV_PARAM_ATIM_WINDOW, 3476d1506e7SBartosz Markowski .bmiss_count_max = WMI_10X_VDEV_PARAM_BMISS_COUNT_MAX, 3486d1506e7SBartosz Markowski .bmiss_first_bcnt = WMI_VDEV_PARAM_UNSUPPORTED, 3496d1506e7SBartosz Markowski .bmiss_final_bcnt = WMI_VDEV_PARAM_UNSUPPORTED, 3506d1506e7SBartosz Markowski .feature_wmm = WMI_10X_VDEV_PARAM_FEATURE_WMM, 3516d1506e7SBartosz Markowski .chwidth = WMI_10X_VDEV_PARAM_CHWIDTH, 3526d1506e7SBartosz Markowski .chextoffset = WMI_10X_VDEV_PARAM_CHEXTOFFSET, 3536d1506e7SBartosz Markowski .disable_htprotection = WMI_10X_VDEV_PARAM_DISABLE_HTPROTECTION, 3546d1506e7SBartosz Markowski .sta_quickkickout = WMI_10X_VDEV_PARAM_STA_QUICKKICKOUT, 3556d1506e7SBartosz Markowski .mgmt_rate = WMI_10X_VDEV_PARAM_MGMT_RATE, 3566d1506e7SBartosz Markowski .protection_mode = WMI_10X_VDEV_PARAM_PROTECTION_MODE, 3576d1506e7SBartosz Markowski .fixed_rate = WMI_10X_VDEV_PARAM_FIXED_RATE, 3586d1506e7SBartosz Markowski .sgi = WMI_10X_VDEV_PARAM_SGI, 3596d1506e7SBartosz Markowski .ldpc = WMI_10X_VDEV_PARAM_LDPC, 3606d1506e7SBartosz Markowski .tx_stbc = WMI_10X_VDEV_PARAM_TX_STBC, 3616d1506e7SBartosz Markowski .rx_stbc = WMI_10X_VDEV_PARAM_RX_STBC, 3626d1506e7SBartosz Markowski .intra_bss_fwd = WMI_10X_VDEV_PARAM_INTRA_BSS_FWD, 3636d1506e7SBartosz Markowski .def_keyid = WMI_10X_VDEV_PARAM_DEF_KEYID, 3646d1506e7SBartosz Markowski .nss = WMI_10X_VDEV_PARAM_NSS, 3656d1506e7SBartosz Markowski .bcast_data_rate = WMI_10X_VDEV_PARAM_BCAST_DATA_RATE, 3666d1506e7SBartosz Markowski .mcast_data_rate = WMI_10X_VDEV_PARAM_MCAST_DATA_RATE, 3676d1506e7SBartosz Markowski .mcast_indicate = WMI_10X_VDEV_PARAM_MCAST_INDICATE, 3686d1506e7SBartosz Markowski .dhcp_indicate = WMI_10X_VDEV_PARAM_DHCP_INDICATE, 3696d1506e7SBartosz Markowski .unknown_dest_indicate = WMI_10X_VDEV_PARAM_UNKNOWN_DEST_INDICATE, 3706d1506e7SBartosz Markowski .ap_keepalive_min_idle_inactive_time_secs = 3716d1506e7SBartosz Markowski WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, 3726d1506e7SBartosz Markowski .ap_keepalive_max_idle_inactive_time_secs = 3736d1506e7SBartosz Markowski WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, 3746d1506e7SBartosz Markowski .ap_keepalive_max_unresponsive_time_secs = 3756d1506e7SBartosz Markowski WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, 3766d1506e7SBartosz Markowski .ap_enable_nawds = WMI_10X_VDEV_PARAM_AP_ENABLE_NAWDS, 3776d1506e7SBartosz Markowski .mcast2ucast_set = WMI_10X_VDEV_PARAM_MCAST2UCAST_SET, 3786d1506e7SBartosz Markowski .enable_rtscts = WMI_10X_VDEV_PARAM_ENABLE_RTSCTS, 3796d1506e7SBartosz Markowski .txbf = WMI_VDEV_PARAM_UNSUPPORTED, 3806d1506e7SBartosz Markowski .packet_powersave = WMI_VDEV_PARAM_UNSUPPORTED, 3816d1506e7SBartosz Markowski .drop_unencry = WMI_VDEV_PARAM_UNSUPPORTED, 3826d1506e7SBartosz Markowski .tx_encap_type = WMI_VDEV_PARAM_UNSUPPORTED, 3836d1506e7SBartosz Markowski .ap_detect_out_of_sync_sleeping_sta_time_secs = 3846d1506e7SBartosz Markowski WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS, 3856d1506e7SBartosz Markowski }; 3866d1506e7SBartosz Markowski 387226a339bSBartosz Markowski static struct wmi_pdev_param_map wmi_pdev_param_map = { 388226a339bSBartosz Markowski .tx_chain_mask = WMI_PDEV_PARAM_TX_CHAIN_MASK, 389226a339bSBartosz Markowski .rx_chain_mask = WMI_PDEV_PARAM_RX_CHAIN_MASK, 390226a339bSBartosz Markowski .txpower_limit2g = WMI_PDEV_PARAM_TXPOWER_LIMIT2G, 391226a339bSBartosz Markowski .txpower_limit5g = WMI_PDEV_PARAM_TXPOWER_LIMIT5G, 392226a339bSBartosz Markowski .txpower_scale = WMI_PDEV_PARAM_TXPOWER_SCALE, 393226a339bSBartosz Markowski .beacon_gen_mode = WMI_PDEV_PARAM_BEACON_GEN_MODE, 394226a339bSBartosz Markowski .beacon_tx_mode = WMI_PDEV_PARAM_BEACON_TX_MODE, 395226a339bSBartosz Markowski .resmgr_offchan_mode = WMI_PDEV_PARAM_RESMGR_OFFCHAN_MODE, 396226a339bSBartosz Markowski .protection_mode = WMI_PDEV_PARAM_PROTECTION_MODE, 397226a339bSBartosz Markowski .dynamic_bw = WMI_PDEV_PARAM_DYNAMIC_BW, 398226a339bSBartosz Markowski .non_agg_sw_retry_th = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH, 399226a339bSBartosz Markowski .agg_sw_retry_th = WMI_PDEV_PARAM_AGG_SW_RETRY_TH, 400226a339bSBartosz Markowski .sta_kickout_th = WMI_PDEV_PARAM_STA_KICKOUT_TH, 401226a339bSBartosz Markowski .ac_aggrsize_scaling = WMI_PDEV_PARAM_AC_AGGRSIZE_SCALING, 402226a339bSBartosz Markowski .ltr_enable = WMI_PDEV_PARAM_LTR_ENABLE, 403226a339bSBartosz Markowski .ltr_ac_latency_be = WMI_PDEV_PARAM_LTR_AC_LATENCY_BE, 404226a339bSBartosz Markowski .ltr_ac_latency_bk = WMI_PDEV_PARAM_LTR_AC_LATENCY_BK, 405226a339bSBartosz Markowski .ltr_ac_latency_vi = WMI_PDEV_PARAM_LTR_AC_LATENCY_VI, 406226a339bSBartosz Markowski .ltr_ac_latency_vo = WMI_PDEV_PARAM_LTR_AC_LATENCY_VO, 407226a339bSBartosz Markowski .ltr_ac_latency_timeout = WMI_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT, 408226a339bSBartosz Markowski .ltr_sleep_override = WMI_PDEV_PARAM_LTR_SLEEP_OVERRIDE, 409226a339bSBartosz Markowski .ltr_rx_override = WMI_PDEV_PARAM_LTR_RX_OVERRIDE, 410226a339bSBartosz Markowski .ltr_tx_activity_timeout = WMI_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT, 411226a339bSBartosz Markowski .l1ss_enable = WMI_PDEV_PARAM_L1SS_ENABLE, 412226a339bSBartosz Markowski .dsleep_enable = WMI_PDEV_PARAM_DSLEEP_ENABLE, 413226a339bSBartosz Markowski .pcielp_txbuf_flush = WMI_PDEV_PARAM_PCIELP_TXBUF_FLUSH, 414226a339bSBartosz Markowski .pcielp_txbuf_watermark = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_EN, 415226a339bSBartosz Markowski .pcielp_txbuf_tmo_en = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_EN, 416226a339bSBartosz Markowski .pcielp_txbuf_tmo_value = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE, 417226a339bSBartosz Markowski .pdev_stats_update_period = WMI_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD, 418226a339bSBartosz Markowski .vdev_stats_update_period = WMI_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD, 419226a339bSBartosz Markowski .peer_stats_update_period = WMI_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD, 420226a339bSBartosz Markowski .bcnflt_stats_update_period = WMI_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, 421226a339bSBartosz Markowski .pmf_qos = WMI_PDEV_PARAM_PMF_QOS, 422226a339bSBartosz Markowski .arp_ac_override = WMI_PDEV_PARAM_ARP_AC_OVERRIDE, 423226a339bSBartosz Markowski .arpdhcp_ac_override = WMI_PDEV_PARAM_UNSUPPORTED, 424226a339bSBartosz Markowski .dcs = WMI_PDEV_PARAM_DCS, 425226a339bSBartosz Markowski .ani_enable = WMI_PDEV_PARAM_ANI_ENABLE, 426226a339bSBartosz Markowski .ani_poll_period = WMI_PDEV_PARAM_ANI_POLL_PERIOD, 427226a339bSBartosz Markowski .ani_listen_period = WMI_PDEV_PARAM_ANI_LISTEN_PERIOD, 428226a339bSBartosz Markowski .ani_ofdm_level = WMI_PDEV_PARAM_ANI_OFDM_LEVEL, 429226a339bSBartosz Markowski .ani_cck_level = WMI_PDEV_PARAM_ANI_CCK_LEVEL, 430226a339bSBartosz Markowski .dyntxchain = WMI_PDEV_PARAM_DYNTXCHAIN, 431226a339bSBartosz Markowski .proxy_sta = WMI_PDEV_PARAM_PROXY_STA, 432226a339bSBartosz Markowski .idle_ps_config = WMI_PDEV_PARAM_IDLE_PS_CONFIG, 433226a339bSBartosz Markowski .power_gating_sleep = WMI_PDEV_PARAM_POWER_GATING_SLEEP, 434226a339bSBartosz Markowski .fast_channel_reset = WMI_PDEV_PARAM_UNSUPPORTED, 435226a339bSBartosz Markowski .burst_dur = WMI_PDEV_PARAM_UNSUPPORTED, 436226a339bSBartosz Markowski .burst_enable = WMI_PDEV_PARAM_UNSUPPORTED, 437226a339bSBartosz Markowski }; 438226a339bSBartosz Markowski 439226a339bSBartosz Markowski static struct wmi_pdev_param_map wmi_10x_pdev_param_map = { 440226a339bSBartosz Markowski .tx_chain_mask = WMI_10X_PDEV_PARAM_TX_CHAIN_MASK, 441226a339bSBartosz Markowski .rx_chain_mask = WMI_10X_PDEV_PARAM_RX_CHAIN_MASK, 442226a339bSBartosz Markowski .txpower_limit2g = WMI_10X_PDEV_PARAM_TXPOWER_LIMIT2G, 443226a339bSBartosz Markowski .txpower_limit5g = WMI_10X_PDEV_PARAM_TXPOWER_LIMIT5G, 444226a339bSBartosz Markowski .txpower_scale = WMI_10X_PDEV_PARAM_TXPOWER_SCALE, 445226a339bSBartosz Markowski .beacon_gen_mode = WMI_10X_PDEV_PARAM_BEACON_GEN_MODE, 446226a339bSBartosz Markowski .beacon_tx_mode = WMI_10X_PDEV_PARAM_BEACON_TX_MODE, 447226a339bSBartosz Markowski .resmgr_offchan_mode = WMI_10X_PDEV_PARAM_RESMGR_OFFCHAN_MODE, 448226a339bSBartosz Markowski .protection_mode = WMI_10X_PDEV_PARAM_PROTECTION_MODE, 449226a339bSBartosz Markowski .dynamic_bw = WMI_10X_PDEV_PARAM_DYNAMIC_BW, 450226a339bSBartosz Markowski .non_agg_sw_retry_th = WMI_10X_PDEV_PARAM_NON_AGG_SW_RETRY_TH, 451226a339bSBartosz Markowski .agg_sw_retry_th = WMI_10X_PDEV_PARAM_AGG_SW_RETRY_TH, 452226a339bSBartosz Markowski .sta_kickout_th = WMI_10X_PDEV_PARAM_STA_KICKOUT_TH, 453226a339bSBartosz Markowski .ac_aggrsize_scaling = WMI_10X_PDEV_PARAM_AC_AGGRSIZE_SCALING, 454226a339bSBartosz Markowski .ltr_enable = WMI_10X_PDEV_PARAM_LTR_ENABLE, 455226a339bSBartosz Markowski .ltr_ac_latency_be = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BE, 456226a339bSBartosz Markowski .ltr_ac_latency_bk = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BK, 457226a339bSBartosz Markowski .ltr_ac_latency_vi = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VI, 458226a339bSBartosz Markowski .ltr_ac_latency_vo = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VO, 459226a339bSBartosz Markowski .ltr_ac_latency_timeout = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT, 460226a339bSBartosz Markowski .ltr_sleep_override = WMI_10X_PDEV_PARAM_LTR_SLEEP_OVERRIDE, 461226a339bSBartosz Markowski .ltr_rx_override = WMI_10X_PDEV_PARAM_LTR_RX_OVERRIDE, 462226a339bSBartosz Markowski .ltr_tx_activity_timeout = WMI_10X_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT, 463226a339bSBartosz Markowski .l1ss_enable = WMI_10X_PDEV_PARAM_L1SS_ENABLE, 464226a339bSBartosz Markowski .dsleep_enable = WMI_10X_PDEV_PARAM_DSLEEP_ENABLE, 465226a339bSBartosz Markowski .pcielp_txbuf_flush = WMI_PDEV_PARAM_UNSUPPORTED, 466226a339bSBartosz Markowski .pcielp_txbuf_watermark = WMI_PDEV_PARAM_UNSUPPORTED, 467226a339bSBartosz Markowski .pcielp_txbuf_tmo_en = WMI_PDEV_PARAM_UNSUPPORTED, 468226a339bSBartosz Markowski .pcielp_txbuf_tmo_value = WMI_PDEV_PARAM_UNSUPPORTED, 469226a339bSBartosz Markowski .pdev_stats_update_period = WMI_10X_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD, 470226a339bSBartosz Markowski .vdev_stats_update_period = WMI_10X_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD, 471226a339bSBartosz Markowski .peer_stats_update_period = WMI_10X_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD, 472226a339bSBartosz Markowski .bcnflt_stats_update_period = 473226a339bSBartosz Markowski WMI_10X_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, 474226a339bSBartosz Markowski .pmf_qos = WMI_10X_PDEV_PARAM_PMF_QOS, 475226a339bSBartosz Markowski .arp_ac_override = WMI_PDEV_PARAM_UNSUPPORTED, 476226a339bSBartosz Markowski .arpdhcp_ac_override = WMI_10X_PDEV_PARAM_ARPDHCP_AC_OVERRIDE, 477226a339bSBartosz Markowski .dcs = WMI_10X_PDEV_PARAM_DCS, 478226a339bSBartosz Markowski .ani_enable = WMI_10X_PDEV_PARAM_ANI_ENABLE, 479226a339bSBartosz Markowski .ani_poll_period = WMI_10X_PDEV_PARAM_ANI_POLL_PERIOD, 480226a339bSBartosz Markowski .ani_listen_period = WMI_10X_PDEV_PARAM_ANI_LISTEN_PERIOD, 481226a339bSBartosz Markowski .ani_ofdm_level = WMI_10X_PDEV_PARAM_ANI_OFDM_LEVEL, 482226a339bSBartosz Markowski .ani_cck_level = WMI_10X_PDEV_PARAM_ANI_CCK_LEVEL, 483226a339bSBartosz Markowski .dyntxchain = WMI_10X_PDEV_PARAM_DYNTXCHAIN, 484226a339bSBartosz Markowski .proxy_sta = WMI_PDEV_PARAM_UNSUPPORTED, 485226a339bSBartosz Markowski .idle_ps_config = WMI_PDEV_PARAM_UNSUPPORTED, 486226a339bSBartosz Markowski .power_gating_sleep = WMI_PDEV_PARAM_UNSUPPORTED, 487226a339bSBartosz Markowski .fast_channel_reset = WMI_10X_PDEV_PARAM_FAST_CHANNEL_RESET, 488226a339bSBartosz Markowski .burst_dur = WMI_10X_PDEV_PARAM_BURST_DUR, 489226a339bSBartosz Markowski .burst_enable = WMI_10X_PDEV_PARAM_BURST_ENABLE, 490226a339bSBartosz Markowski }; 491226a339bSBartosz Markowski 4925e3dd157SKalle Valo int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) 4935e3dd157SKalle Valo { 4945e3dd157SKalle Valo int ret; 4955e3dd157SKalle Valo ret = wait_for_completion_timeout(&ar->wmi.service_ready, 4965e3dd157SKalle Valo WMI_SERVICE_READY_TIMEOUT_HZ); 4975e3dd157SKalle Valo return ret; 4985e3dd157SKalle Valo } 4995e3dd157SKalle Valo 5005e3dd157SKalle Valo int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar) 5015e3dd157SKalle Valo { 5025e3dd157SKalle Valo int ret; 5035e3dd157SKalle Valo ret = wait_for_completion_timeout(&ar->wmi.unified_ready, 5045e3dd157SKalle Valo WMI_UNIFIED_READY_TIMEOUT_HZ); 5055e3dd157SKalle Valo return ret; 5065e3dd157SKalle Valo } 5075e3dd157SKalle Valo 5085e3dd157SKalle Valo static struct sk_buff *ath10k_wmi_alloc_skb(u32 len) 5095e3dd157SKalle Valo { 5105e3dd157SKalle Valo struct sk_buff *skb; 5115e3dd157SKalle Valo u32 round_len = roundup(len, 4); 5125e3dd157SKalle Valo 5135e3dd157SKalle Valo skb = ath10k_htc_alloc_skb(WMI_SKB_HEADROOM + round_len); 5145e3dd157SKalle Valo if (!skb) 5155e3dd157SKalle Valo return NULL; 5165e3dd157SKalle Valo 5175e3dd157SKalle Valo skb_reserve(skb, WMI_SKB_HEADROOM); 5185e3dd157SKalle Valo if (!IS_ALIGNED((unsigned long)skb->data, 4)) 5195e3dd157SKalle Valo ath10k_warn("Unaligned WMI skb\n"); 5205e3dd157SKalle Valo 5215e3dd157SKalle Valo skb_put(skb, round_len); 5225e3dd157SKalle Valo memset(skb->data, 0, round_len); 5235e3dd157SKalle Valo 5245e3dd157SKalle Valo return skb; 5255e3dd157SKalle Valo } 5265e3dd157SKalle Valo 5275e3dd157SKalle Valo static void ath10k_wmi_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) 5285e3dd157SKalle Valo { 5295e3dd157SKalle Valo dev_kfree_skb(skb); 5305e3dd157SKalle Valo } 5315e3dd157SKalle Valo 532be8b3943SMichal Kazior static int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb, 533ce42870eSBartosz Markowski u32 cmd_id) 5345e3dd157SKalle Valo { 5355e3dd157SKalle Valo struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); 5365e3dd157SKalle Valo struct wmi_cmd_hdr *cmd_hdr; 537be8b3943SMichal Kazior int ret; 5385e3dd157SKalle Valo u32 cmd = 0; 5395e3dd157SKalle Valo 5405e3dd157SKalle Valo if (skb_push(skb, sizeof(struct wmi_cmd_hdr)) == NULL) 5415e3dd157SKalle Valo return -ENOMEM; 5425e3dd157SKalle Valo 5435e3dd157SKalle Valo cmd |= SM(cmd_id, WMI_CMD_HDR_CMD_ID); 5445e3dd157SKalle Valo 5455e3dd157SKalle Valo cmd_hdr = (struct wmi_cmd_hdr *)skb->data; 5465e3dd157SKalle Valo cmd_hdr->cmd_id = __cpu_to_le32(cmd); 5475e3dd157SKalle Valo 5485e3dd157SKalle Valo memset(skb_cb, 0, sizeof(*skb_cb)); 549be8b3943SMichal Kazior ret = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb); 550be8b3943SMichal Kazior trace_ath10k_wmi_cmd(cmd_id, skb->data, skb->len, ret); 5515e3dd157SKalle Valo 552be8b3943SMichal Kazior if (ret) 553be8b3943SMichal Kazior goto err_pull; 5545e3dd157SKalle Valo 5555e3dd157SKalle Valo return 0; 556be8b3943SMichal Kazior 557be8b3943SMichal Kazior err_pull: 558be8b3943SMichal Kazior skb_pull(skb, sizeof(struct wmi_cmd_hdr)); 559be8b3943SMichal Kazior return ret; 560be8b3943SMichal Kazior } 561be8b3943SMichal Kazior 562ed54388aSMichal Kazior static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif) 563ed54388aSMichal Kazior { 564ed54388aSMichal Kazior int ret; 565ed54388aSMichal Kazior 566ed54388aSMichal Kazior lockdep_assert_held(&arvif->ar->data_lock); 567ed54388aSMichal Kazior 568ed54388aSMichal Kazior if (arvif->beacon == NULL) 569ed54388aSMichal Kazior return; 570ed54388aSMichal Kazior 571748afc47SMichal Kazior if (arvif->beacon_sent) 572748afc47SMichal Kazior return; 573ed54388aSMichal Kazior 574748afc47SMichal Kazior ret = ath10k_wmi_beacon_send_ref_nowait(arvif); 575ed54388aSMichal Kazior if (ret) 576ed54388aSMichal Kazior return; 577ed54388aSMichal Kazior 578748afc47SMichal Kazior /* We need to retain the arvif->beacon reference for DMA unmapping and 579748afc47SMichal Kazior * freeing the skbuff later. */ 580748afc47SMichal Kazior arvif->beacon_sent = true; 581ed54388aSMichal Kazior } 582ed54388aSMichal Kazior 583ed54388aSMichal Kazior static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac, 584ed54388aSMichal Kazior struct ieee80211_vif *vif) 585ed54388aSMichal Kazior { 586ed54388aSMichal Kazior struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); 587ed54388aSMichal Kazior 588ed54388aSMichal Kazior ath10k_wmi_tx_beacon_nowait(arvif); 589ed54388aSMichal Kazior } 590ed54388aSMichal Kazior 591ed54388aSMichal Kazior static void ath10k_wmi_tx_beacons_nowait(struct ath10k *ar) 592ed54388aSMichal Kazior { 593ed54388aSMichal Kazior spin_lock_bh(&ar->data_lock); 594ed54388aSMichal Kazior ieee80211_iterate_active_interfaces_atomic(ar->hw, 595ed54388aSMichal Kazior IEEE80211_IFACE_ITER_NORMAL, 596ed54388aSMichal Kazior ath10k_wmi_tx_beacons_iter, 597ed54388aSMichal Kazior NULL); 598ed54388aSMichal Kazior spin_unlock_bh(&ar->data_lock); 599ed54388aSMichal Kazior } 600ed54388aSMichal Kazior 60112acbc43SMichal Kazior static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar) 602be8b3943SMichal Kazior { 603ed54388aSMichal Kazior /* try to send pending beacons first. they take priority */ 604ed54388aSMichal Kazior ath10k_wmi_tx_beacons_nowait(ar); 605ed54388aSMichal Kazior 606be8b3943SMichal Kazior wake_up(&ar->wmi.tx_credits_wq); 607be8b3943SMichal Kazior } 608be8b3943SMichal Kazior 609be8b3943SMichal Kazior static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, 610ce42870eSBartosz Markowski u32 cmd_id) 611be8b3943SMichal Kazior { 61234957b25SBartosz Markowski int ret = -EOPNOTSUPP; 613be8b3943SMichal Kazior 61456b84287SKalle Valo might_sleep(); 61556b84287SKalle Valo 61634957b25SBartosz Markowski if (cmd_id == WMI_CMD_UNSUPPORTED) { 61755321559SBartosz Markowski ath10k_warn("wmi command %d is not supported by firmware\n", 61855321559SBartosz Markowski cmd_id); 61955321559SBartosz Markowski return ret; 62055321559SBartosz Markowski } 621be8b3943SMichal Kazior 622be8b3943SMichal Kazior wait_event_timeout(ar->wmi.tx_credits_wq, ({ 623ed54388aSMichal Kazior /* try to send pending beacons first. they take priority */ 624ed54388aSMichal Kazior ath10k_wmi_tx_beacons_nowait(ar); 625ed54388aSMichal Kazior 626be8b3943SMichal Kazior ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id); 627be8b3943SMichal Kazior (ret != -EAGAIN); 628be8b3943SMichal Kazior }), 3*HZ); 629be8b3943SMichal Kazior 630be8b3943SMichal Kazior if (ret) 631be8b3943SMichal Kazior dev_kfree_skb_any(skb); 632be8b3943SMichal Kazior 633be8b3943SMichal Kazior return ret; 6345e3dd157SKalle Valo } 6355e3dd157SKalle Valo 6365e00d31aSBartosz Markowski int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb) 6375e00d31aSBartosz Markowski { 6385e00d31aSBartosz Markowski int ret = 0; 6395e00d31aSBartosz Markowski struct wmi_mgmt_tx_cmd *cmd; 6405e00d31aSBartosz Markowski struct ieee80211_hdr *hdr; 6415e00d31aSBartosz Markowski struct sk_buff *wmi_skb; 6425e00d31aSBartosz Markowski struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 6435e00d31aSBartosz Markowski int len; 6445e00d31aSBartosz Markowski u16 fc; 6455e00d31aSBartosz Markowski 6465e00d31aSBartosz Markowski hdr = (struct ieee80211_hdr *)skb->data; 6475e00d31aSBartosz Markowski fc = le16_to_cpu(hdr->frame_control); 6485e00d31aSBartosz Markowski 6495e00d31aSBartosz Markowski if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control))) 6505e00d31aSBartosz Markowski return -EINVAL; 6515e00d31aSBartosz Markowski 6525e00d31aSBartosz Markowski len = sizeof(cmd->hdr) + skb->len; 6535e00d31aSBartosz Markowski len = round_up(len, 4); 6545e00d31aSBartosz Markowski 6555e00d31aSBartosz Markowski wmi_skb = ath10k_wmi_alloc_skb(len); 6565e00d31aSBartosz Markowski if (!wmi_skb) 6575e00d31aSBartosz Markowski return -ENOMEM; 6585e00d31aSBartosz Markowski 6595e00d31aSBartosz Markowski cmd = (struct wmi_mgmt_tx_cmd *)wmi_skb->data; 6605e00d31aSBartosz Markowski 6615e00d31aSBartosz Markowski cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(skb)->vdev_id); 6625e00d31aSBartosz Markowski cmd->hdr.tx_rate = 0; 6635e00d31aSBartosz Markowski cmd->hdr.tx_power = 0; 6645e00d31aSBartosz Markowski cmd->hdr.buf_len = __cpu_to_le32((u32)(skb->len)); 6655e00d31aSBartosz Markowski 6665e00d31aSBartosz Markowski memcpy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr), ETH_ALEN); 6675e00d31aSBartosz Markowski memcpy(cmd->buf, skb->data, skb->len); 6685e00d31aSBartosz Markowski 6695e00d31aSBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n", 6705e00d31aSBartosz Markowski wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE, 6715e00d31aSBartosz Markowski fc & IEEE80211_FCTL_STYPE); 6725e00d31aSBartosz Markowski 6735e00d31aSBartosz Markowski /* Send the management frame buffer to the target */ 6745e00d31aSBartosz Markowski ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid); 6755fb5e41fSMichal Kazior if (ret) 6765e00d31aSBartosz Markowski return ret; 6775e00d31aSBartosz Markowski 6785e00d31aSBartosz Markowski /* TODO: report tx status to mac80211 - temporary just ACK */ 6795e00d31aSBartosz Markowski info->flags |= IEEE80211_TX_STAT_ACK; 6805e00d31aSBartosz Markowski ieee80211_tx_status_irqsafe(ar->hw, skb); 6815e00d31aSBartosz Markowski 6825e00d31aSBartosz Markowski return ret; 6835e00d31aSBartosz Markowski } 6845e00d31aSBartosz Markowski 6855e3dd157SKalle Valo static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb) 6865e3dd157SKalle Valo { 6875e3dd157SKalle Valo struct wmi_scan_event *event = (struct wmi_scan_event *)skb->data; 6885e3dd157SKalle Valo enum wmi_scan_event_type event_type; 6895e3dd157SKalle Valo enum wmi_scan_completion_reason reason; 6905e3dd157SKalle Valo u32 freq; 6915e3dd157SKalle Valo u32 req_id; 6925e3dd157SKalle Valo u32 scan_id; 6935e3dd157SKalle Valo u32 vdev_id; 6945e3dd157SKalle Valo 6955e3dd157SKalle Valo event_type = __le32_to_cpu(event->event_type); 6965e3dd157SKalle Valo reason = __le32_to_cpu(event->reason); 6975e3dd157SKalle Valo freq = __le32_to_cpu(event->channel_freq); 6985e3dd157SKalle Valo req_id = __le32_to_cpu(event->scan_req_id); 6995e3dd157SKalle Valo scan_id = __le32_to_cpu(event->scan_id); 7005e3dd157SKalle Valo vdev_id = __le32_to_cpu(event->vdev_id); 7015e3dd157SKalle Valo 7025e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENTID\n"); 7035e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 7045e3dd157SKalle Valo "scan event type %d reason %d freq %d req_id %d " 7055e3dd157SKalle Valo "scan_id %d vdev_id %d\n", 7065e3dd157SKalle Valo event_type, reason, freq, req_id, scan_id, vdev_id); 7075e3dd157SKalle Valo 7085e3dd157SKalle Valo spin_lock_bh(&ar->data_lock); 7095e3dd157SKalle Valo 7105e3dd157SKalle Valo switch (event_type) { 7115e3dd157SKalle Valo case WMI_SCAN_EVENT_STARTED: 7125e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_STARTED\n"); 7135e3dd157SKalle Valo if (ar->scan.in_progress && ar->scan.is_roc) 7145e3dd157SKalle Valo ieee80211_ready_on_channel(ar->hw); 7155e3dd157SKalle Valo 7165e3dd157SKalle Valo complete(&ar->scan.started); 7175e3dd157SKalle Valo break; 7185e3dd157SKalle Valo case WMI_SCAN_EVENT_COMPLETED: 7195e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_COMPLETED\n"); 7205e3dd157SKalle Valo switch (reason) { 7215e3dd157SKalle Valo case WMI_SCAN_REASON_COMPLETED: 7225e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_COMPLETED\n"); 7235e3dd157SKalle Valo break; 7245e3dd157SKalle Valo case WMI_SCAN_REASON_CANCELLED: 7255e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_CANCELED\n"); 7265e3dd157SKalle Valo break; 7275e3dd157SKalle Valo case WMI_SCAN_REASON_PREEMPTED: 7285e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_PREEMPTED\n"); 7295e3dd157SKalle Valo break; 7305e3dd157SKalle Valo case WMI_SCAN_REASON_TIMEDOUT: 7315e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_TIMEDOUT\n"); 7325e3dd157SKalle Valo break; 7335e3dd157SKalle Valo default: 7345e3dd157SKalle Valo break; 7355e3dd157SKalle Valo } 7365e3dd157SKalle Valo 7375e3dd157SKalle Valo ar->scan_channel = NULL; 7385e3dd157SKalle Valo if (!ar->scan.in_progress) { 7395e3dd157SKalle Valo ath10k_warn("no scan requested, ignoring\n"); 7405e3dd157SKalle Valo break; 7415e3dd157SKalle Valo } 7425e3dd157SKalle Valo 7435e3dd157SKalle Valo if (ar->scan.is_roc) { 7445e3dd157SKalle Valo ath10k_offchan_tx_purge(ar); 7455e3dd157SKalle Valo 7465e3dd157SKalle Valo if (!ar->scan.aborting) 7475e3dd157SKalle Valo ieee80211_remain_on_channel_expired(ar->hw); 7485e3dd157SKalle Valo } else { 7495e3dd157SKalle Valo ieee80211_scan_completed(ar->hw, ar->scan.aborting); 7505e3dd157SKalle Valo } 7515e3dd157SKalle Valo 7525e3dd157SKalle Valo del_timer(&ar->scan.timeout); 7535e3dd157SKalle Valo complete_all(&ar->scan.completed); 7545e3dd157SKalle Valo ar->scan.in_progress = false; 7555e3dd157SKalle Valo break; 7565e3dd157SKalle Valo case WMI_SCAN_EVENT_BSS_CHANNEL: 7575e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_BSS_CHANNEL\n"); 7585e3dd157SKalle Valo ar->scan_channel = NULL; 7595e3dd157SKalle Valo break; 7605e3dd157SKalle Valo case WMI_SCAN_EVENT_FOREIGN_CHANNEL: 7615e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_FOREIGN_CHANNEL\n"); 7625e3dd157SKalle Valo ar->scan_channel = ieee80211_get_channel(ar->hw->wiphy, freq); 7635e3dd157SKalle Valo if (ar->scan.in_progress && ar->scan.is_roc && 7645e3dd157SKalle Valo ar->scan.roc_freq == freq) { 7655e3dd157SKalle Valo complete(&ar->scan.on_channel); 7665e3dd157SKalle Valo } 7675e3dd157SKalle Valo break; 7685e3dd157SKalle Valo case WMI_SCAN_EVENT_DEQUEUED: 7695e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_DEQUEUED\n"); 7705e3dd157SKalle Valo break; 7715e3dd157SKalle Valo case WMI_SCAN_EVENT_PREEMPTED: 7725e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENT_PREEMPTED\n"); 7735e3dd157SKalle Valo break; 7745e3dd157SKalle Valo case WMI_SCAN_EVENT_START_FAILED: 7755e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENT_START_FAILED\n"); 7765e3dd157SKalle Valo break; 7775e3dd157SKalle Valo default: 7785e3dd157SKalle Valo break; 7795e3dd157SKalle Valo } 7805e3dd157SKalle Valo 7815e3dd157SKalle Valo spin_unlock_bh(&ar->data_lock); 7825e3dd157SKalle Valo return 0; 7835e3dd157SKalle Valo } 7845e3dd157SKalle Valo 7855e3dd157SKalle Valo static inline enum ieee80211_band phy_mode_to_band(u32 phy_mode) 7865e3dd157SKalle Valo { 7875e3dd157SKalle Valo enum ieee80211_band band; 7885e3dd157SKalle Valo 7895e3dd157SKalle Valo switch (phy_mode) { 7905e3dd157SKalle Valo case MODE_11A: 7915e3dd157SKalle Valo case MODE_11NA_HT20: 7925e3dd157SKalle Valo case MODE_11NA_HT40: 7935e3dd157SKalle Valo case MODE_11AC_VHT20: 7945e3dd157SKalle Valo case MODE_11AC_VHT40: 7955e3dd157SKalle Valo case MODE_11AC_VHT80: 7965e3dd157SKalle Valo band = IEEE80211_BAND_5GHZ; 7975e3dd157SKalle Valo break; 7985e3dd157SKalle Valo case MODE_11G: 7995e3dd157SKalle Valo case MODE_11B: 8005e3dd157SKalle Valo case MODE_11GONLY: 8015e3dd157SKalle Valo case MODE_11NG_HT20: 8025e3dd157SKalle Valo case MODE_11NG_HT40: 8035e3dd157SKalle Valo case MODE_11AC_VHT20_2G: 8045e3dd157SKalle Valo case MODE_11AC_VHT40_2G: 8055e3dd157SKalle Valo case MODE_11AC_VHT80_2G: 8065e3dd157SKalle Valo default: 8075e3dd157SKalle Valo band = IEEE80211_BAND_2GHZ; 8085e3dd157SKalle Valo } 8095e3dd157SKalle Valo 8105e3dd157SKalle Valo return band; 8115e3dd157SKalle Valo } 8125e3dd157SKalle Valo 8135e3dd157SKalle Valo static inline u8 get_rate_idx(u32 rate, enum ieee80211_band band) 8145e3dd157SKalle Valo { 8155e3dd157SKalle Valo u8 rate_idx = 0; 8165e3dd157SKalle Valo 8175e3dd157SKalle Valo /* rate in Kbps */ 8185e3dd157SKalle Valo switch (rate) { 8195e3dd157SKalle Valo case 1000: 8205e3dd157SKalle Valo rate_idx = 0; 8215e3dd157SKalle Valo break; 8225e3dd157SKalle Valo case 2000: 8235e3dd157SKalle Valo rate_idx = 1; 8245e3dd157SKalle Valo break; 8255e3dd157SKalle Valo case 5500: 8265e3dd157SKalle Valo rate_idx = 2; 8275e3dd157SKalle Valo break; 8285e3dd157SKalle Valo case 11000: 8295e3dd157SKalle Valo rate_idx = 3; 8305e3dd157SKalle Valo break; 8315e3dd157SKalle Valo case 6000: 8325e3dd157SKalle Valo rate_idx = 4; 8335e3dd157SKalle Valo break; 8345e3dd157SKalle Valo case 9000: 8355e3dd157SKalle Valo rate_idx = 5; 8365e3dd157SKalle Valo break; 8375e3dd157SKalle Valo case 12000: 8385e3dd157SKalle Valo rate_idx = 6; 8395e3dd157SKalle Valo break; 8405e3dd157SKalle Valo case 18000: 8415e3dd157SKalle Valo rate_idx = 7; 8425e3dd157SKalle Valo break; 8435e3dd157SKalle Valo case 24000: 8445e3dd157SKalle Valo rate_idx = 8; 8455e3dd157SKalle Valo break; 8465e3dd157SKalle Valo case 36000: 8475e3dd157SKalle Valo rate_idx = 9; 8485e3dd157SKalle Valo break; 8495e3dd157SKalle Valo case 48000: 8505e3dd157SKalle Valo rate_idx = 10; 8515e3dd157SKalle Valo break; 8525e3dd157SKalle Valo case 54000: 8535e3dd157SKalle Valo rate_idx = 11; 8545e3dd157SKalle Valo break; 8555e3dd157SKalle Valo default: 8565e3dd157SKalle Valo break; 8575e3dd157SKalle Valo } 8585e3dd157SKalle Valo 8595e3dd157SKalle Valo if (band == IEEE80211_BAND_5GHZ) { 8605e3dd157SKalle Valo if (rate_idx > 3) 8615e3dd157SKalle Valo /* Omit CCK rates */ 8625e3dd157SKalle Valo rate_idx -= 4; 8635e3dd157SKalle Valo else 8645e3dd157SKalle Valo rate_idx = 0; 8655e3dd157SKalle Valo } 8665e3dd157SKalle Valo 8675e3dd157SKalle Valo return rate_idx; 8685e3dd157SKalle Valo } 8695e3dd157SKalle Valo 8705e3dd157SKalle Valo static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) 8715e3dd157SKalle Valo { 8720d9b0438SMichal Kazior struct wmi_mgmt_rx_event_v1 *ev_v1; 8730d9b0438SMichal Kazior struct wmi_mgmt_rx_event_v2 *ev_v2; 8740d9b0438SMichal Kazior struct wmi_mgmt_rx_hdr_v1 *ev_hdr; 8755e3dd157SKalle Valo struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 876453cdb61SMichal Kazior struct ieee80211_channel *ch; 8775e3dd157SKalle Valo struct ieee80211_hdr *hdr; 8785e3dd157SKalle Valo u32 rx_status; 8795e3dd157SKalle Valo u32 channel; 8805e3dd157SKalle Valo u32 phy_mode; 8815e3dd157SKalle Valo u32 snr; 8825e3dd157SKalle Valo u32 rate; 8835e3dd157SKalle Valo u32 buf_len; 8845e3dd157SKalle Valo u16 fc; 8850d9b0438SMichal Kazior int pull_len; 8865e3dd157SKalle Valo 8870d9b0438SMichal Kazior if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) { 8880d9b0438SMichal Kazior ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data; 8890d9b0438SMichal Kazior ev_hdr = &ev_v2->hdr.v1; 8900d9b0438SMichal Kazior pull_len = sizeof(*ev_v2); 8910d9b0438SMichal Kazior } else { 8920d9b0438SMichal Kazior ev_v1 = (struct wmi_mgmt_rx_event_v1 *)skb->data; 8930d9b0438SMichal Kazior ev_hdr = &ev_v1->hdr; 8940d9b0438SMichal Kazior pull_len = sizeof(*ev_v1); 8950d9b0438SMichal Kazior } 8960d9b0438SMichal Kazior 8970d9b0438SMichal Kazior channel = __le32_to_cpu(ev_hdr->channel); 8980d9b0438SMichal Kazior buf_len = __le32_to_cpu(ev_hdr->buf_len); 8990d9b0438SMichal Kazior rx_status = __le32_to_cpu(ev_hdr->status); 9000d9b0438SMichal Kazior snr = __le32_to_cpu(ev_hdr->snr); 9010d9b0438SMichal Kazior phy_mode = __le32_to_cpu(ev_hdr->phy_mode); 9020d9b0438SMichal Kazior rate = __le32_to_cpu(ev_hdr->rate); 9035e3dd157SKalle Valo 9045e3dd157SKalle Valo memset(status, 0, sizeof(*status)); 9055e3dd157SKalle Valo 9065e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, 9075e3dd157SKalle Valo "event mgmt rx status %08x\n", rx_status); 9085e3dd157SKalle Valo 909e8a50f8bSMarek Puzyniak if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) { 910e8a50f8bSMarek Puzyniak dev_kfree_skb(skb); 911e8a50f8bSMarek Puzyniak return 0; 912e8a50f8bSMarek Puzyniak } 913e8a50f8bSMarek Puzyniak 9145e3dd157SKalle Valo if (rx_status & WMI_RX_STATUS_ERR_DECRYPT) { 9155e3dd157SKalle Valo dev_kfree_skb(skb); 9165e3dd157SKalle Valo return 0; 9175e3dd157SKalle Valo } 9185e3dd157SKalle Valo 9195e3dd157SKalle Valo if (rx_status & WMI_RX_STATUS_ERR_KEY_CACHE_MISS) { 9205e3dd157SKalle Valo dev_kfree_skb(skb); 9215e3dd157SKalle Valo return 0; 9225e3dd157SKalle Valo } 9235e3dd157SKalle Valo 9245e3dd157SKalle Valo if (rx_status & WMI_RX_STATUS_ERR_CRC) 9255e3dd157SKalle Valo status->flag |= RX_FLAG_FAILED_FCS_CRC; 9265e3dd157SKalle Valo if (rx_status & WMI_RX_STATUS_ERR_MIC) 9275e3dd157SKalle Valo status->flag |= RX_FLAG_MMIC_ERROR; 9285e3dd157SKalle Valo 929453cdb61SMichal Kazior /* HW can Rx CCK rates on 5GHz. In that case phy_mode is set to 930453cdb61SMichal Kazior * MODE_11B. This means phy_mode is not a reliable source for the band 931453cdb61SMichal Kazior * of mgmt rx. */ 932453cdb61SMichal Kazior 933453cdb61SMichal Kazior ch = ar->scan_channel; 934453cdb61SMichal Kazior if (!ch) 935453cdb61SMichal Kazior ch = ar->rx_channel; 936453cdb61SMichal Kazior 937453cdb61SMichal Kazior if (ch) { 938453cdb61SMichal Kazior status->band = ch->band; 939453cdb61SMichal Kazior 940453cdb61SMichal Kazior if (phy_mode == MODE_11B && 941453cdb61SMichal Kazior status->band == IEEE80211_BAND_5GHZ) 942453cdb61SMichal Kazior ath10k_dbg(ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n"); 943453cdb61SMichal Kazior } else { 944453cdb61SMichal Kazior ath10k_warn("using (unreliable) phy_mode to extract band for mgmt rx\n"); 9455e3dd157SKalle Valo status->band = phy_mode_to_band(phy_mode); 946453cdb61SMichal Kazior } 947453cdb61SMichal Kazior 9485e3dd157SKalle Valo status->freq = ieee80211_channel_to_frequency(channel, status->band); 9495e3dd157SKalle Valo status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; 9505e3dd157SKalle Valo status->rate_idx = get_rate_idx(rate, status->band); 9515e3dd157SKalle Valo 9520d9b0438SMichal Kazior skb_pull(skb, pull_len); 9535e3dd157SKalle Valo 9545e3dd157SKalle Valo hdr = (struct ieee80211_hdr *)skb->data; 9555e3dd157SKalle Valo fc = le16_to_cpu(hdr->frame_control); 9565e3dd157SKalle Valo 9572b6a6a90SMichal Kazior /* FW delivers WEP Shared Auth frame with Protected Bit set and 9582b6a6a90SMichal Kazior * encrypted payload. However in case of PMF it delivers decrypted 9592b6a6a90SMichal Kazior * frames with Protected Bit set. */ 9602b6a6a90SMichal Kazior if (ieee80211_has_protected(hdr->frame_control) && 9612b6a6a90SMichal Kazior !ieee80211_is_auth(hdr->frame_control)) { 9625e3dd157SKalle Valo status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED | 9635e3dd157SKalle Valo RX_FLAG_MMIC_STRIPPED; 9645e3dd157SKalle Valo hdr->frame_control = __cpu_to_le16(fc & 9655e3dd157SKalle Valo ~IEEE80211_FCTL_PROTECTED); 9665e3dd157SKalle Valo } 9675e3dd157SKalle Valo 9685e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, 9695e3dd157SKalle Valo "event mgmt rx skb %p len %d ftype %02x stype %02x\n", 9705e3dd157SKalle Valo skb, skb->len, 9715e3dd157SKalle Valo fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE); 9725e3dd157SKalle Valo 9735e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, 9745e3dd157SKalle Valo "event mgmt rx freq %d band %d snr %d, rate_idx %d\n", 9755e3dd157SKalle Valo status->freq, status->band, status->signal, 9765e3dd157SKalle Valo status->rate_idx); 9775e3dd157SKalle Valo 9785e3dd157SKalle Valo /* 9795e3dd157SKalle Valo * packets from HTC come aligned to 4byte boundaries 9805e3dd157SKalle Valo * because they can originally come in along with a trailer 9815e3dd157SKalle Valo */ 9825e3dd157SKalle Valo skb_trim(skb, buf_len); 9835e3dd157SKalle Valo 9845e3dd157SKalle Valo ieee80211_rx(ar->hw, skb); 9855e3dd157SKalle Valo return 0; 9865e3dd157SKalle Valo } 9875e3dd157SKalle Valo 9882e1dea40SMichal Kazior static int freq_to_idx(struct ath10k *ar, int freq) 9892e1dea40SMichal Kazior { 9902e1dea40SMichal Kazior struct ieee80211_supported_band *sband; 9912e1dea40SMichal Kazior int band, ch, idx = 0; 9922e1dea40SMichal Kazior 9932e1dea40SMichal Kazior for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { 9942e1dea40SMichal Kazior sband = ar->hw->wiphy->bands[band]; 9952e1dea40SMichal Kazior if (!sband) 9962e1dea40SMichal Kazior continue; 9972e1dea40SMichal Kazior 9982e1dea40SMichal Kazior for (ch = 0; ch < sband->n_channels; ch++, idx++) 9992e1dea40SMichal Kazior if (sband->channels[ch].center_freq == freq) 10002e1dea40SMichal Kazior goto exit; 10012e1dea40SMichal Kazior } 10022e1dea40SMichal Kazior 10032e1dea40SMichal Kazior exit: 10042e1dea40SMichal Kazior return idx; 10052e1dea40SMichal Kazior } 10062e1dea40SMichal Kazior 10075e3dd157SKalle Valo static void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb) 10085e3dd157SKalle Valo { 10092e1dea40SMichal Kazior struct wmi_chan_info_event *ev; 10102e1dea40SMichal Kazior struct survey_info *survey; 10112e1dea40SMichal Kazior u32 err_code, freq, cmd_flags, noise_floor, rx_clear_count, cycle_count; 10122e1dea40SMichal Kazior int idx; 10132e1dea40SMichal Kazior 10142e1dea40SMichal Kazior ev = (struct wmi_chan_info_event *)skb->data; 10152e1dea40SMichal Kazior 10162e1dea40SMichal Kazior err_code = __le32_to_cpu(ev->err_code); 10172e1dea40SMichal Kazior freq = __le32_to_cpu(ev->freq); 10182e1dea40SMichal Kazior cmd_flags = __le32_to_cpu(ev->cmd_flags); 10192e1dea40SMichal Kazior noise_floor = __le32_to_cpu(ev->noise_floor); 10202e1dea40SMichal Kazior rx_clear_count = __le32_to_cpu(ev->rx_clear_count); 10212e1dea40SMichal Kazior cycle_count = __le32_to_cpu(ev->cycle_count); 10222e1dea40SMichal Kazior 10232e1dea40SMichal Kazior ath10k_dbg(ATH10K_DBG_WMI, 10242e1dea40SMichal Kazior "chan info err_code %d freq %d cmd_flags %d noise_floor %d rx_clear_count %d cycle_count %d\n", 10252e1dea40SMichal Kazior err_code, freq, cmd_flags, noise_floor, rx_clear_count, 10262e1dea40SMichal Kazior cycle_count); 10272e1dea40SMichal Kazior 10282e1dea40SMichal Kazior spin_lock_bh(&ar->data_lock); 10292e1dea40SMichal Kazior 10302e1dea40SMichal Kazior if (!ar->scan.in_progress) { 10312e1dea40SMichal Kazior ath10k_warn("chan info event without a scan request?\n"); 10322e1dea40SMichal Kazior goto exit; 10332e1dea40SMichal Kazior } 10342e1dea40SMichal Kazior 10352e1dea40SMichal Kazior idx = freq_to_idx(ar, freq); 10362e1dea40SMichal Kazior if (idx >= ARRAY_SIZE(ar->survey)) { 10372e1dea40SMichal Kazior ath10k_warn("chan info: invalid frequency %d (idx %d out of bounds)\n", 10382e1dea40SMichal Kazior freq, idx); 10392e1dea40SMichal Kazior goto exit; 10402e1dea40SMichal Kazior } 10412e1dea40SMichal Kazior 10422e1dea40SMichal Kazior if (cmd_flags & WMI_CHAN_INFO_FLAG_COMPLETE) { 10432e1dea40SMichal Kazior /* During scanning chan info is reported twice for each 10442e1dea40SMichal Kazior * visited channel. The reported cycle count is global 10452e1dea40SMichal Kazior * and per-channel cycle count must be calculated */ 10462e1dea40SMichal Kazior 10472e1dea40SMichal Kazior cycle_count -= ar->survey_last_cycle_count; 10482e1dea40SMichal Kazior rx_clear_count -= ar->survey_last_rx_clear_count; 10492e1dea40SMichal Kazior 10502e1dea40SMichal Kazior survey = &ar->survey[idx]; 10512e1dea40SMichal Kazior survey->channel_time = WMI_CHAN_INFO_MSEC(cycle_count); 10522e1dea40SMichal Kazior survey->channel_time_rx = WMI_CHAN_INFO_MSEC(rx_clear_count); 10532e1dea40SMichal Kazior survey->noise = noise_floor; 10542e1dea40SMichal Kazior survey->filled = SURVEY_INFO_CHANNEL_TIME | 10552e1dea40SMichal Kazior SURVEY_INFO_CHANNEL_TIME_RX | 10562e1dea40SMichal Kazior SURVEY_INFO_NOISE_DBM; 10572e1dea40SMichal Kazior } 10582e1dea40SMichal Kazior 10592e1dea40SMichal Kazior ar->survey_last_rx_clear_count = rx_clear_count; 10602e1dea40SMichal Kazior ar->survey_last_cycle_count = cycle_count; 10612e1dea40SMichal Kazior 10622e1dea40SMichal Kazior exit: 10632e1dea40SMichal Kazior spin_unlock_bh(&ar->data_lock); 10645e3dd157SKalle Valo } 10655e3dd157SKalle Valo 10665e3dd157SKalle Valo static void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb) 10675e3dd157SKalle Valo { 10685e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_ECHO_EVENTID\n"); 10695e3dd157SKalle Valo } 10705e3dd157SKalle Valo 1071869526b9SKalle Valo static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb) 10725e3dd157SKalle Valo { 1073869526b9SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi event debug mesg len %d\n", 1074869526b9SKalle Valo skb->len); 1075869526b9SKalle Valo 1076869526b9SKalle Valo trace_ath10k_wmi_dbglog(skb->data, skb->len); 1077869526b9SKalle Valo 1078869526b9SKalle Valo return 0; 10795e3dd157SKalle Valo } 10805e3dd157SKalle Valo 10815e3dd157SKalle Valo static void ath10k_wmi_event_update_stats(struct ath10k *ar, 10825e3dd157SKalle Valo struct sk_buff *skb) 10835e3dd157SKalle Valo { 10845e3dd157SKalle Valo struct wmi_stats_event *ev = (struct wmi_stats_event *)skb->data; 10855e3dd157SKalle Valo 10865e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n"); 10875e3dd157SKalle Valo 10885e3dd157SKalle Valo ath10k_debug_read_target_stats(ar, ev); 10895e3dd157SKalle Valo } 10905e3dd157SKalle Valo 10915e3dd157SKalle Valo static void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, 10925e3dd157SKalle Valo struct sk_buff *skb) 10935e3dd157SKalle Valo { 10945e3dd157SKalle Valo struct wmi_vdev_start_response_event *ev; 10955e3dd157SKalle Valo 10965e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_START_RESP_EVENTID\n"); 10975e3dd157SKalle Valo 10985e3dd157SKalle Valo ev = (struct wmi_vdev_start_response_event *)skb->data; 10995e3dd157SKalle Valo 11005e3dd157SKalle Valo if (WARN_ON(__le32_to_cpu(ev->status))) 11015e3dd157SKalle Valo return; 11025e3dd157SKalle Valo 11035e3dd157SKalle Valo complete(&ar->vdev_setup_done); 11045e3dd157SKalle Valo } 11055e3dd157SKalle Valo 11065e3dd157SKalle Valo static void ath10k_wmi_event_vdev_stopped(struct ath10k *ar, 11075e3dd157SKalle Valo struct sk_buff *skb) 11085e3dd157SKalle Valo { 11095e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_STOPPED_EVENTID\n"); 11105e3dd157SKalle Valo complete(&ar->vdev_setup_done); 11115e3dd157SKalle Valo } 11125e3dd157SKalle Valo 11135e3dd157SKalle Valo static void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar, 11145e3dd157SKalle Valo struct sk_buff *skb) 11155e3dd157SKalle Valo { 11165a13e76eSKalle Valo struct wmi_peer_sta_kickout_event *ev; 11175a13e76eSKalle Valo struct ieee80211_sta *sta; 11185a13e76eSKalle Valo 11195a13e76eSKalle Valo ev = (struct wmi_peer_sta_kickout_event *)skb->data; 11205a13e76eSKalle Valo 11215a13e76eSKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi event peer sta kickout %pM\n", 11225a13e76eSKalle Valo ev->peer_macaddr.addr); 11235a13e76eSKalle Valo 11245a13e76eSKalle Valo rcu_read_lock(); 11255a13e76eSKalle Valo 11265a13e76eSKalle Valo sta = ieee80211_find_sta_by_ifaddr(ar->hw, ev->peer_macaddr.addr, NULL); 11275a13e76eSKalle Valo if (!sta) { 11285a13e76eSKalle Valo ath10k_warn("Spurious quick kickout for STA %pM\n", 11295a13e76eSKalle Valo ev->peer_macaddr.addr); 11305a13e76eSKalle Valo goto exit; 11315a13e76eSKalle Valo } 11325a13e76eSKalle Valo 11335a13e76eSKalle Valo ieee80211_report_low_ack(sta, 10); 11345a13e76eSKalle Valo 11355a13e76eSKalle Valo exit: 11365a13e76eSKalle Valo rcu_read_unlock(); 11375e3dd157SKalle Valo } 11385e3dd157SKalle Valo 11395e3dd157SKalle Valo /* 11405e3dd157SKalle Valo * FIXME 11415e3dd157SKalle Valo * 11425e3dd157SKalle Valo * We don't report to mac80211 sleep state of connected 11435e3dd157SKalle Valo * stations. Due to this mac80211 can't fill in TIM IE 11445e3dd157SKalle Valo * correctly. 11455e3dd157SKalle Valo * 11465e3dd157SKalle Valo * I know of no way of getting nullfunc frames that contain 11475e3dd157SKalle Valo * sleep transition from connected stations - these do not 11485e3dd157SKalle Valo * seem to be sent from the target to the host. There also 11495e3dd157SKalle Valo * doesn't seem to be a dedicated event for that. So the 11505e3dd157SKalle Valo * only way left to do this would be to read tim_bitmap 11515e3dd157SKalle Valo * during SWBA. 11525e3dd157SKalle Valo * 11535e3dd157SKalle Valo * We could probably try using tim_bitmap from SWBA to tell 11545e3dd157SKalle Valo * mac80211 which stations are asleep and which are not. The 11555e3dd157SKalle Valo * problem here is calling mac80211 functions so many times 11565e3dd157SKalle Valo * could take too long and make us miss the time to submit 11575e3dd157SKalle Valo * the beacon to the target. 11585e3dd157SKalle Valo * 11595e3dd157SKalle Valo * So as a workaround we try to extend the TIM IE if there 11605e3dd157SKalle Valo * is unicast buffered for stations with aid > 7 and fill it 11615e3dd157SKalle Valo * in ourselves. 11625e3dd157SKalle Valo */ 11635e3dd157SKalle Valo static void ath10k_wmi_update_tim(struct ath10k *ar, 11645e3dd157SKalle Valo struct ath10k_vif *arvif, 11655e3dd157SKalle Valo struct sk_buff *bcn, 11665e3dd157SKalle Valo struct wmi_bcn_info *bcn_info) 11675e3dd157SKalle Valo { 11685e3dd157SKalle Valo struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)bcn->data; 11695e3dd157SKalle Valo struct ieee80211_tim_ie *tim; 11705e3dd157SKalle Valo u8 *ies, *ie; 11715e3dd157SKalle Valo u8 ie_len, pvm_len; 11725e3dd157SKalle Valo 11735e3dd157SKalle Valo /* if next SWBA has no tim_changed the tim_bitmap is garbage. 11745e3dd157SKalle Valo * we must copy the bitmap upon change and reuse it later */ 11755e3dd157SKalle Valo if (__le32_to_cpu(bcn_info->tim_info.tim_changed)) { 11765e3dd157SKalle Valo int i; 11775e3dd157SKalle Valo 11785e3dd157SKalle Valo BUILD_BUG_ON(sizeof(arvif->u.ap.tim_bitmap) != 11795e3dd157SKalle Valo sizeof(bcn_info->tim_info.tim_bitmap)); 11805e3dd157SKalle Valo 11815e3dd157SKalle Valo for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++) { 11825e3dd157SKalle Valo __le32 t = bcn_info->tim_info.tim_bitmap[i / 4]; 11835e3dd157SKalle Valo u32 v = __le32_to_cpu(t); 11845e3dd157SKalle Valo arvif->u.ap.tim_bitmap[i] = (v >> ((i % 4) * 8)) & 0xFF; 11855e3dd157SKalle Valo } 11865e3dd157SKalle Valo 11875e3dd157SKalle Valo /* FW reports either length 0 or 16 11885e3dd157SKalle Valo * so we calculate this on our own */ 11895e3dd157SKalle Valo arvif->u.ap.tim_len = 0; 11905e3dd157SKalle Valo for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++) 11915e3dd157SKalle Valo if (arvif->u.ap.tim_bitmap[i]) 11925e3dd157SKalle Valo arvif->u.ap.tim_len = i; 11935e3dd157SKalle Valo 11945e3dd157SKalle Valo arvif->u.ap.tim_len++; 11955e3dd157SKalle Valo } 11965e3dd157SKalle Valo 11975e3dd157SKalle Valo ies = bcn->data; 11985e3dd157SKalle Valo ies += ieee80211_hdrlen(hdr->frame_control); 11995e3dd157SKalle Valo ies += 12; /* fixed parameters */ 12005e3dd157SKalle Valo 12015e3dd157SKalle Valo ie = (u8 *)cfg80211_find_ie(WLAN_EID_TIM, ies, 12025e3dd157SKalle Valo (u8 *)skb_tail_pointer(bcn) - ies); 12035e3dd157SKalle Valo if (!ie) { 120409af8f85SMichal Kazior if (arvif->vdev_type != WMI_VDEV_TYPE_IBSS) 12055e3dd157SKalle Valo ath10k_warn("no tim ie found;\n"); 12065e3dd157SKalle Valo return; 12075e3dd157SKalle Valo } 12085e3dd157SKalle Valo 12095e3dd157SKalle Valo tim = (void *)ie + 2; 12105e3dd157SKalle Valo ie_len = ie[1]; 12115e3dd157SKalle Valo pvm_len = ie_len - 3; /* exclude dtim count, dtim period, bmap ctl */ 12125e3dd157SKalle Valo 12135e3dd157SKalle Valo if (pvm_len < arvif->u.ap.tim_len) { 12145e3dd157SKalle Valo int expand_size = sizeof(arvif->u.ap.tim_bitmap) - pvm_len; 12155e3dd157SKalle Valo int move_size = skb_tail_pointer(bcn) - (ie + 2 + ie_len); 12165e3dd157SKalle Valo void *next_ie = ie + 2 + ie_len; 12175e3dd157SKalle Valo 12185e3dd157SKalle Valo if (skb_put(bcn, expand_size)) { 12195e3dd157SKalle Valo memmove(next_ie + expand_size, next_ie, move_size); 12205e3dd157SKalle Valo 12215e3dd157SKalle Valo ie[1] += expand_size; 12225e3dd157SKalle Valo ie_len += expand_size; 12235e3dd157SKalle Valo pvm_len += expand_size; 12245e3dd157SKalle Valo } else { 12255e3dd157SKalle Valo ath10k_warn("tim expansion failed\n"); 12265e3dd157SKalle Valo } 12275e3dd157SKalle Valo } 12285e3dd157SKalle Valo 12295e3dd157SKalle Valo if (pvm_len > sizeof(arvif->u.ap.tim_bitmap)) { 12305e3dd157SKalle Valo ath10k_warn("tim pvm length is too great (%d)\n", pvm_len); 12315e3dd157SKalle Valo return; 12325e3dd157SKalle Valo } 12335e3dd157SKalle Valo 12345e3dd157SKalle Valo tim->bitmap_ctrl = !!__le32_to_cpu(bcn_info->tim_info.tim_mcast); 12355e3dd157SKalle Valo memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len); 12365e3dd157SKalle Valo 1237748afc47SMichal Kazior if (tim->dtim_count == 0) { 1238748afc47SMichal Kazior ATH10K_SKB_CB(bcn)->bcn.dtim_zero = true; 1239748afc47SMichal Kazior 1240748afc47SMichal Kazior if (__le32_to_cpu(bcn_info->tim_info.tim_mcast) == 1) 1241748afc47SMichal Kazior ATH10K_SKB_CB(bcn)->bcn.deliver_cab = true; 1242748afc47SMichal Kazior } 1243748afc47SMichal Kazior 12445e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n", 12455e3dd157SKalle Valo tim->dtim_count, tim->dtim_period, 12465e3dd157SKalle Valo tim->bitmap_ctrl, pvm_len); 12475e3dd157SKalle Valo } 12485e3dd157SKalle Valo 12495e3dd157SKalle Valo static void ath10k_p2p_fill_noa_ie(u8 *data, u32 len, 12505e3dd157SKalle Valo struct wmi_p2p_noa_info *noa) 12515e3dd157SKalle Valo { 12525e3dd157SKalle Valo struct ieee80211_p2p_noa_attr *noa_attr; 12535e3dd157SKalle Valo u8 ctwindow_oppps = noa->ctwindow_oppps; 12545e3dd157SKalle Valo u8 ctwindow = ctwindow_oppps >> WMI_P2P_OPPPS_CTWINDOW_OFFSET; 12555e3dd157SKalle Valo bool oppps = !!(ctwindow_oppps & WMI_P2P_OPPPS_ENABLE_BIT); 12565e3dd157SKalle Valo __le16 *noa_attr_len; 12575e3dd157SKalle Valo u16 attr_len; 12585e3dd157SKalle Valo u8 noa_descriptors = noa->num_descriptors; 12595e3dd157SKalle Valo int i; 12605e3dd157SKalle Valo 12615e3dd157SKalle Valo /* P2P IE */ 12625e3dd157SKalle Valo data[0] = WLAN_EID_VENDOR_SPECIFIC; 12635e3dd157SKalle Valo data[1] = len - 2; 12645e3dd157SKalle Valo data[2] = (WLAN_OUI_WFA >> 16) & 0xff; 12655e3dd157SKalle Valo data[3] = (WLAN_OUI_WFA >> 8) & 0xff; 12665e3dd157SKalle Valo data[4] = (WLAN_OUI_WFA >> 0) & 0xff; 12675e3dd157SKalle Valo data[5] = WLAN_OUI_TYPE_WFA_P2P; 12685e3dd157SKalle Valo 12695e3dd157SKalle Valo /* NOA ATTR */ 12705e3dd157SKalle Valo data[6] = IEEE80211_P2P_ATTR_ABSENCE_NOTICE; 12715e3dd157SKalle Valo noa_attr_len = (__le16 *)&data[7]; /* 2 bytes */ 12725e3dd157SKalle Valo noa_attr = (struct ieee80211_p2p_noa_attr *)&data[9]; 12735e3dd157SKalle Valo 12745e3dd157SKalle Valo noa_attr->index = noa->index; 12755e3dd157SKalle Valo noa_attr->oppps_ctwindow = ctwindow; 12765e3dd157SKalle Valo if (oppps) 12775e3dd157SKalle Valo noa_attr->oppps_ctwindow |= IEEE80211_P2P_OPPPS_ENABLE_BIT; 12785e3dd157SKalle Valo 12795e3dd157SKalle Valo for (i = 0; i < noa_descriptors; i++) { 12805e3dd157SKalle Valo noa_attr->desc[i].count = 12815e3dd157SKalle Valo __le32_to_cpu(noa->descriptors[i].type_count); 12825e3dd157SKalle Valo noa_attr->desc[i].duration = noa->descriptors[i].duration; 12835e3dd157SKalle Valo noa_attr->desc[i].interval = noa->descriptors[i].interval; 12845e3dd157SKalle Valo noa_attr->desc[i].start_time = noa->descriptors[i].start_time; 12855e3dd157SKalle Valo } 12865e3dd157SKalle Valo 12875e3dd157SKalle Valo attr_len = 2; /* index + oppps_ctwindow */ 12885e3dd157SKalle Valo attr_len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc); 12895e3dd157SKalle Valo *noa_attr_len = __cpu_to_le16(attr_len); 12905e3dd157SKalle Valo } 12915e3dd157SKalle Valo 12925e3dd157SKalle Valo static u32 ath10k_p2p_calc_noa_ie_len(struct wmi_p2p_noa_info *noa) 12935e3dd157SKalle Valo { 12945e3dd157SKalle Valo u32 len = 0; 12955e3dd157SKalle Valo u8 noa_descriptors = noa->num_descriptors; 12965e3dd157SKalle Valo u8 opp_ps_info = noa->ctwindow_oppps; 12975e3dd157SKalle Valo bool opps_enabled = !!(opp_ps_info & WMI_P2P_OPPPS_ENABLE_BIT); 12985e3dd157SKalle Valo 12995e3dd157SKalle Valo 13005e3dd157SKalle Valo if (!noa_descriptors && !opps_enabled) 13015e3dd157SKalle Valo return len; 13025e3dd157SKalle Valo 13035e3dd157SKalle Valo len += 1 + 1 + 4; /* EID + len + OUI */ 13045e3dd157SKalle Valo len += 1 + 2; /* noa attr + attr len */ 13055e3dd157SKalle Valo len += 1 + 1; /* index + oppps_ctwindow */ 13065e3dd157SKalle Valo len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc); 13075e3dd157SKalle Valo 13085e3dd157SKalle Valo return len; 13095e3dd157SKalle Valo } 13105e3dd157SKalle Valo 13115e3dd157SKalle Valo static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif, 13125e3dd157SKalle Valo struct sk_buff *bcn, 13135e3dd157SKalle Valo struct wmi_bcn_info *bcn_info) 13145e3dd157SKalle Valo { 13155e3dd157SKalle Valo struct wmi_p2p_noa_info *noa = &bcn_info->p2p_noa_info; 13165e3dd157SKalle Valo u8 *new_data, *old_data = arvif->u.ap.noa_data; 13175e3dd157SKalle Valo u32 new_len; 13185e3dd157SKalle Valo 13195e3dd157SKalle Valo if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) 13205e3dd157SKalle Valo return; 13215e3dd157SKalle Valo 13225e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, "noa changed: %d\n", noa->changed); 13235e3dd157SKalle Valo if (noa->changed & WMI_P2P_NOA_CHANGED_BIT) { 13245e3dd157SKalle Valo new_len = ath10k_p2p_calc_noa_ie_len(noa); 13255e3dd157SKalle Valo if (!new_len) 13265e3dd157SKalle Valo goto cleanup; 13275e3dd157SKalle Valo 13285e3dd157SKalle Valo new_data = kmalloc(new_len, GFP_ATOMIC); 13295e3dd157SKalle Valo if (!new_data) 13305e3dd157SKalle Valo goto cleanup; 13315e3dd157SKalle Valo 13325e3dd157SKalle Valo ath10k_p2p_fill_noa_ie(new_data, new_len, noa); 13335e3dd157SKalle Valo 13345e3dd157SKalle Valo spin_lock_bh(&ar->data_lock); 13355e3dd157SKalle Valo arvif->u.ap.noa_data = new_data; 13365e3dd157SKalle Valo arvif->u.ap.noa_len = new_len; 13375e3dd157SKalle Valo spin_unlock_bh(&ar->data_lock); 13385e3dd157SKalle Valo kfree(old_data); 13395e3dd157SKalle Valo } 13405e3dd157SKalle Valo 13415e3dd157SKalle Valo if (arvif->u.ap.noa_data) 13425e3dd157SKalle Valo if (!pskb_expand_head(bcn, 0, arvif->u.ap.noa_len, GFP_ATOMIC)) 13435e3dd157SKalle Valo memcpy(skb_put(bcn, arvif->u.ap.noa_len), 13445e3dd157SKalle Valo arvif->u.ap.noa_data, 13455e3dd157SKalle Valo arvif->u.ap.noa_len); 13465e3dd157SKalle Valo return; 13475e3dd157SKalle Valo 13485e3dd157SKalle Valo cleanup: 13495e3dd157SKalle Valo spin_lock_bh(&ar->data_lock); 13505e3dd157SKalle Valo arvif->u.ap.noa_data = NULL; 13515e3dd157SKalle Valo arvif->u.ap.noa_len = 0; 13525e3dd157SKalle Valo spin_unlock_bh(&ar->data_lock); 13535e3dd157SKalle Valo kfree(old_data); 13545e3dd157SKalle Valo } 13555e3dd157SKalle Valo 13565e3dd157SKalle Valo 13575e3dd157SKalle Valo static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) 13585e3dd157SKalle Valo { 13595e3dd157SKalle Valo struct wmi_host_swba_event *ev; 13605e3dd157SKalle Valo u32 map; 13615e3dd157SKalle Valo int i = -1; 13625e3dd157SKalle Valo struct wmi_bcn_info *bcn_info; 13635e3dd157SKalle Valo struct ath10k_vif *arvif; 13645e3dd157SKalle Valo struct sk_buff *bcn; 13655e3dd157SKalle Valo int vdev_id = 0; 13665e3dd157SKalle Valo 13675e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, "WMI_HOST_SWBA_EVENTID\n"); 13685e3dd157SKalle Valo 13695e3dd157SKalle Valo ev = (struct wmi_host_swba_event *)skb->data; 13705e3dd157SKalle Valo map = __le32_to_cpu(ev->vdev_map); 13715e3dd157SKalle Valo 13725e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, "host swba:\n" 13735e3dd157SKalle Valo "-vdev map 0x%x\n", 13745e3dd157SKalle Valo ev->vdev_map); 13755e3dd157SKalle Valo 13765e3dd157SKalle Valo for (; map; map >>= 1, vdev_id++) { 13775e3dd157SKalle Valo if (!(map & 0x1)) 13785e3dd157SKalle Valo continue; 13795e3dd157SKalle Valo 13805e3dd157SKalle Valo i++; 13815e3dd157SKalle Valo 13825e3dd157SKalle Valo if (i >= WMI_MAX_AP_VDEV) { 13835e3dd157SKalle Valo ath10k_warn("swba has corrupted vdev map\n"); 13845e3dd157SKalle Valo break; 13855e3dd157SKalle Valo } 13865e3dd157SKalle Valo 13875e3dd157SKalle Valo bcn_info = &ev->bcn_info[i]; 13885e3dd157SKalle Valo 13895e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, 13905e3dd157SKalle Valo "-bcn_info[%d]:\n" 13915e3dd157SKalle Valo "--tim_len %d\n" 13925e3dd157SKalle Valo "--tim_mcast %d\n" 13935e3dd157SKalle Valo "--tim_changed %d\n" 13945e3dd157SKalle Valo "--tim_num_ps_pending %d\n" 13955e3dd157SKalle Valo "--tim_bitmap 0x%08x%08x%08x%08x\n", 13965e3dd157SKalle Valo i, 13975e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_len), 13985e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_mcast), 13995e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_changed), 14005e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_num_ps_pending), 14015e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_bitmap[3]), 14025e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_bitmap[2]), 14035e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_bitmap[1]), 14045e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_bitmap[0])); 14055e3dd157SKalle Valo 14065e3dd157SKalle Valo arvif = ath10k_get_arvif(ar, vdev_id); 14075e3dd157SKalle Valo if (arvif == NULL) { 14085e3dd157SKalle Valo ath10k_warn("no vif for vdev_id %d found\n", vdev_id); 14095e3dd157SKalle Valo continue; 14105e3dd157SKalle Valo } 14115e3dd157SKalle Valo 1412c2df44b3SMichal Kazior /* There are no completions for beacons so wait for next SWBA 1413c2df44b3SMichal Kazior * before telling mac80211 to decrement CSA counter 1414c2df44b3SMichal Kazior * 1415c2df44b3SMichal Kazior * Once CSA counter is completed stop sending beacons until 1416c2df44b3SMichal Kazior * actual channel switch is done */ 1417c2df44b3SMichal Kazior if (arvif->vif->csa_active && 1418c2df44b3SMichal Kazior ieee80211_csa_is_complete(arvif->vif)) { 1419c2df44b3SMichal Kazior ieee80211_csa_finish(arvif->vif); 1420c2df44b3SMichal Kazior continue; 1421c2df44b3SMichal Kazior } 1422c2df44b3SMichal Kazior 14235e3dd157SKalle Valo bcn = ieee80211_beacon_get(ar->hw, arvif->vif); 14245e3dd157SKalle Valo if (!bcn) { 14255e3dd157SKalle Valo ath10k_warn("could not get mac80211 beacon\n"); 14265e3dd157SKalle Valo continue; 14275e3dd157SKalle Valo } 14285e3dd157SKalle Valo 14295e3dd157SKalle Valo ath10k_tx_h_seq_no(bcn); 14305e3dd157SKalle Valo ath10k_wmi_update_tim(ar, arvif, bcn, bcn_info); 14315e3dd157SKalle Valo ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info); 14325e3dd157SKalle Valo 1433ed54388aSMichal Kazior spin_lock_bh(&ar->data_lock); 1434748afc47SMichal Kazior 1435ed54388aSMichal Kazior if (arvif->beacon) { 1436748afc47SMichal Kazior if (!arvif->beacon_sent) 1437ed54388aSMichal Kazior ath10k_warn("SWBA overrun on vdev %d\n", 1438ed54388aSMichal Kazior arvif->vdev_id); 1439748afc47SMichal Kazior 1440748afc47SMichal Kazior ath10k_skb_unmap(ar->dev, arvif->beacon); 1441ed54388aSMichal Kazior dev_kfree_skb_any(arvif->beacon); 1442ed54388aSMichal Kazior } 14435e3dd157SKalle Valo 1444748afc47SMichal Kazior ath10k_skb_map(ar->dev, bcn); 1445748afc47SMichal Kazior 1446ed54388aSMichal Kazior arvif->beacon = bcn; 1447748afc47SMichal Kazior arvif->beacon_sent = false; 14485e3dd157SKalle Valo 1449ed54388aSMichal Kazior ath10k_wmi_tx_beacon_nowait(arvif); 1450ed54388aSMichal Kazior spin_unlock_bh(&ar->data_lock); 14515e3dd157SKalle Valo } 14525e3dd157SKalle Valo } 14535e3dd157SKalle Valo 14545e3dd157SKalle Valo static void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, 14555e3dd157SKalle Valo struct sk_buff *skb) 14565e3dd157SKalle Valo { 14575e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_TBTTOFFSET_UPDATE_EVENTID\n"); 14585e3dd157SKalle Valo } 14595e3dd157SKalle Valo 14609702c686SJanusz Dziedzic static void ath10k_dfs_radar_report(struct ath10k *ar, 14619702c686SJanusz Dziedzic struct wmi_single_phyerr_rx_event *event, 14629702c686SJanusz Dziedzic struct phyerr_radar_report *rr, 14639702c686SJanusz Dziedzic u64 tsf) 14649702c686SJanusz Dziedzic { 14659702c686SJanusz Dziedzic u32 reg0, reg1, tsf32l; 14669702c686SJanusz Dziedzic struct pulse_event pe; 14679702c686SJanusz Dziedzic u64 tsf64; 14689702c686SJanusz Dziedzic u8 rssi, width; 14699702c686SJanusz Dziedzic 14709702c686SJanusz Dziedzic reg0 = __le32_to_cpu(rr->reg0); 14719702c686SJanusz Dziedzic reg1 = __le32_to_cpu(rr->reg1); 14729702c686SJanusz Dziedzic 14739702c686SJanusz Dziedzic ath10k_dbg(ATH10K_DBG_REGULATORY, 14749702c686SJanusz Dziedzic "wmi phyerr radar report chirp %d max_width %d agc_total_gain %d pulse_delta_diff %d\n", 14759702c686SJanusz Dziedzic MS(reg0, RADAR_REPORT_REG0_PULSE_IS_CHIRP), 14769702c686SJanusz Dziedzic MS(reg0, RADAR_REPORT_REG0_PULSE_IS_MAX_WIDTH), 14779702c686SJanusz Dziedzic MS(reg0, RADAR_REPORT_REG0_AGC_TOTAL_GAIN), 14789702c686SJanusz Dziedzic MS(reg0, RADAR_REPORT_REG0_PULSE_DELTA_DIFF)); 14799702c686SJanusz Dziedzic ath10k_dbg(ATH10K_DBG_REGULATORY, 14809702c686SJanusz Dziedzic "wmi phyerr radar report pulse_delta_pean %d pulse_sidx %d fft_valid %d agc_mb_gain %d subchan_mask %d\n", 14819702c686SJanusz Dziedzic MS(reg0, RADAR_REPORT_REG0_PULSE_DELTA_PEAK), 14829702c686SJanusz Dziedzic MS(reg0, RADAR_REPORT_REG0_PULSE_SIDX), 14839702c686SJanusz Dziedzic MS(reg1, RADAR_REPORT_REG1_PULSE_SRCH_FFT_VALID), 14849702c686SJanusz Dziedzic MS(reg1, RADAR_REPORT_REG1_PULSE_AGC_MB_GAIN), 14859702c686SJanusz Dziedzic MS(reg1, RADAR_REPORT_REG1_PULSE_SUBCHAN_MASK)); 14869702c686SJanusz Dziedzic ath10k_dbg(ATH10K_DBG_REGULATORY, 14879702c686SJanusz Dziedzic "wmi phyerr radar report pulse_tsf_offset 0x%X pulse_dur: %d\n", 14889702c686SJanusz Dziedzic MS(reg1, RADAR_REPORT_REG1_PULSE_TSF_OFFSET), 14899702c686SJanusz Dziedzic MS(reg1, RADAR_REPORT_REG1_PULSE_DUR)); 14909702c686SJanusz Dziedzic 14919702c686SJanusz Dziedzic if (!ar->dfs_detector) 14929702c686SJanusz Dziedzic return; 14939702c686SJanusz Dziedzic 14949702c686SJanusz Dziedzic /* report event to DFS pattern detector */ 14959702c686SJanusz Dziedzic tsf32l = __le32_to_cpu(event->hdr.tsf_timestamp); 14969702c686SJanusz Dziedzic tsf64 = tsf & (~0xFFFFFFFFULL); 14979702c686SJanusz Dziedzic tsf64 |= tsf32l; 14989702c686SJanusz Dziedzic 14999702c686SJanusz Dziedzic width = MS(reg1, RADAR_REPORT_REG1_PULSE_DUR); 15009702c686SJanusz Dziedzic rssi = event->hdr.rssi_combined; 15019702c686SJanusz Dziedzic 15029702c686SJanusz Dziedzic /* hardware store this as 8 bit signed value, 15039702c686SJanusz Dziedzic * set to zero if negative number 15049702c686SJanusz Dziedzic */ 15059702c686SJanusz Dziedzic if (rssi & 0x80) 15069702c686SJanusz Dziedzic rssi = 0; 15079702c686SJanusz Dziedzic 15089702c686SJanusz Dziedzic pe.ts = tsf64; 15099702c686SJanusz Dziedzic pe.freq = ar->hw->conf.chandef.chan->center_freq; 15109702c686SJanusz Dziedzic pe.width = width; 15119702c686SJanusz Dziedzic pe.rssi = rssi; 15129702c686SJanusz Dziedzic 15139702c686SJanusz Dziedzic ath10k_dbg(ATH10K_DBG_REGULATORY, 15149702c686SJanusz Dziedzic "dfs add pulse freq: %d, width: %d, rssi %d, tsf: %llX\n", 15159702c686SJanusz Dziedzic pe.freq, pe.width, pe.rssi, pe.ts); 15169702c686SJanusz Dziedzic 15179702c686SJanusz Dziedzic ATH10K_DFS_STAT_INC(ar, pulses_detected); 15189702c686SJanusz Dziedzic 15199702c686SJanusz Dziedzic if (!ar->dfs_detector->add_pulse(ar->dfs_detector, &pe)) { 15209702c686SJanusz Dziedzic ath10k_dbg(ATH10K_DBG_REGULATORY, 15219702c686SJanusz Dziedzic "dfs no pulse pattern detected, yet\n"); 15229702c686SJanusz Dziedzic return; 15239702c686SJanusz Dziedzic } 15249702c686SJanusz Dziedzic 15259702c686SJanusz Dziedzic ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs radar detected\n"); 15269702c686SJanusz Dziedzic ATH10K_DFS_STAT_INC(ar, radar_detected); 15277d9b40b4SMarek Puzyniak 15287d9b40b4SMarek Puzyniak /* Control radar events reporting in debugfs file 15297d9b40b4SMarek Puzyniak dfs_block_radar_events */ 15307d9b40b4SMarek Puzyniak if (ar->dfs_block_radar_events) { 15317d9b40b4SMarek Puzyniak ath10k_info("DFS Radar detected, but ignored as requested\n"); 15327d9b40b4SMarek Puzyniak return; 15337d9b40b4SMarek Puzyniak } 15347d9b40b4SMarek Puzyniak 15359702c686SJanusz Dziedzic ieee80211_radar_detected(ar->hw); 15369702c686SJanusz Dziedzic } 15379702c686SJanusz Dziedzic 15389702c686SJanusz Dziedzic static int ath10k_dfs_fft_report(struct ath10k *ar, 15399702c686SJanusz Dziedzic struct wmi_single_phyerr_rx_event *event, 15409702c686SJanusz Dziedzic struct phyerr_fft_report *fftr, 15419702c686SJanusz Dziedzic u64 tsf) 15429702c686SJanusz Dziedzic { 15439702c686SJanusz Dziedzic u32 reg0, reg1; 15449702c686SJanusz Dziedzic u8 rssi, peak_mag; 15459702c686SJanusz Dziedzic 15469702c686SJanusz Dziedzic reg0 = __le32_to_cpu(fftr->reg0); 15479702c686SJanusz Dziedzic reg1 = __le32_to_cpu(fftr->reg1); 15489702c686SJanusz Dziedzic rssi = event->hdr.rssi_combined; 15499702c686SJanusz Dziedzic 15509702c686SJanusz Dziedzic ath10k_dbg(ATH10K_DBG_REGULATORY, 15519702c686SJanusz Dziedzic "wmi phyerr fft report total_gain_db %d base_pwr_db %d fft_chn_idx %d peak_sidx %d\n", 15529702c686SJanusz Dziedzic MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB), 15539702c686SJanusz Dziedzic MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB), 15549702c686SJanusz Dziedzic MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX), 15559702c686SJanusz Dziedzic MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX)); 15569702c686SJanusz Dziedzic ath10k_dbg(ATH10K_DBG_REGULATORY, 15579702c686SJanusz Dziedzic "wmi phyerr fft report rel_pwr_db %d avgpwr_db %d peak_mag %d num_store_bin %d\n", 15589702c686SJanusz Dziedzic MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB), 15599702c686SJanusz Dziedzic MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB), 15609702c686SJanusz Dziedzic MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG), 15619702c686SJanusz Dziedzic MS(reg1, SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB)); 15629702c686SJanusz Dziedzic 15639702c686SJanusz Dziedzic peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG); 15649702c686SJanusz Dziedzic 15659702c686SJanusz Dziedzic /* false event detection */ 15669702c686SJanusz Dziedzic if (rssi == DFS_RSSI_POSSIBLY_FALSE && 15679702c686SJanusz Dziedzic peak_mag < 2 * DFS_PEAK_MAG_THOLD_POSSIBLY_FALSE) { 15689702c686SJanusz Dziedzic ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs false pulse detected\n"); 15699702c686SJanusz Dziedzic ATH10K_DFS_STAT_INC(ar, pulses_discarded); 15709702c686SJanusz Dziedzic return -EINVAL; 15719702c686SJanusz Dziedzic } 15729702c686SJanusz Dziedzic 15739702c686SJanusz Dziedzic return 0; 15749702c686SJanusz Dziedzic } 15759702c686SJanusz Dziedzic 15769702c686SJanusz Dziedzic static void ath10k_wmi_event_dfs(struct ath10k *ar, 15779702c686SJanusz Dziedzic struct wmi_single_phyerr_rx_event *event, 15789702c686SJanusz Dziedzic u64 tsf) 15799702c686SJanusz Dziedzic { 15809702c686SJanusz Dziedzic int buf_len, tlv_len, res, i = 0; 15819702c686SJanusz Dziedzic struct phyerr_tlv *tlv; 15829702c686SJanusz Dziedzic struct phyerr_radar_report *rr; 15839702c686SJanusz Dziedzic struct phyerr_fft_report *fftr; 15849702c686SJanusz Dziedzic u8 *tlv_buf; 15859702c686SJanusz Dziedzic 15869702c686SJanusz Dziedzic buf_len = __le32_to_cpu(event->hdr.buf_len); 15879702c686SJanusz Dziedzic ath10k_dbg(ATH10K_DBG_REGULATORY, 15889702c686SJanusz Dziedzic "wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n", 15899702c686SJanusz Dziedzic event->hdr.phy_err_code, event->hdr.rssi_combined, 15909702c686SJanusz Dziedzic __le32_to_cpu(event->hdr.tsf_timestamp), tsf, buf_len); 15919702c686SJanusz Dziedzic 15929702c686SJanusz Dziedzic /* Skip event if DFS disabled */ 15939702c686SJanusz Dziedzic if (!config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) 15949702c686SJanusz Dziedzic return; 15959702c686SJanusz Dziedzic 15969702c686SJanusz Dziedzic ATH10K_DFS_STAT_INC(ar, pulses_total); 15979702c686SJanusz Dziedzic 15989702c686SJanusz Dziedzic while (i < buf_len) { 15999702c686SJanusz Dziedzic if (i + sizeof(*tlv) > buf_len) { 16009702c686SJanusz Dziedzic ath10k_warn("too short buf for tlv header (%d)\n", i); 16019702c686SJanusz Dziedzic return; 16029702c686SJanusz Dziedzic } 16039702c686SJanusz Dziedzic 16049702c686SJanusz Dziedzic tlv = (struct phyerr_tlv *)&event->bufp[i]; 16059702c686SJanusz Dziedzic tlv_len = __le16_to_cpu(tlv->len); 16069702c686SJanusz Dziedzic tlv_buf = &event->bufp[i + sizeof(*tlv)]; 16079702c686SJanusz Dziedzic ath10k_dbg(ATH10K_DBG_REGULATORY, 16089702c686SJanusz Dziedzic "wmi event dfs tlv_len %d tlv_tag 0x%02X tlv_sig 0x%02X\n", 16099702c686SJanusz Dziedzic tlv_len, tlv->tag, tlv->sig); 16109702c686SJanusz Dziedzic 16119702c686SJanusz Dziedzic switch (tlv->tag) { 16129702c686SJanusz Dziedzic case PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY: 16139702c686SJanusz Dziedzic if (i + sizeof(*tlv) + sizeof(*rr) > buf_len) { 16149702c686SJanusz Dziedzic ath10k_warn("too short radar pulse summary (%d)\n", 16159702c686SJanusz Dziedzic i); 16169702c686SJanusz Dziedzic return; 16179702c686SJanusz Dziedzic } 16189702c686SJanusz Dziedzic 16199702c686SJanusz Dziedzic rr = (struct phyerr_radar_report *)tlv_buf; 16209702c686SJanusz Dziedzic ath10k_dfs_radar_report(ar, event, rr, tsf); 16219702c686SJanusz Dziedzic break; 16229702c686SJanusz Dziedzic case PHYERR_TLV_TAG_SEARCH_FFT_REPORT: 16239702c686SJanusz Dziedzic if (i + sizeof(*tlv) + sizeof(*fftr) > buf_len) { 16249702c686SJanusz Dziedzic ath10k_warn("too short fft report (%d)\n", i); 16259702c686SJanusz Dziedzic return; 16269702c686SJanusz Dziedzic } 16279702c686SJanusz Dziedzic 16289702c686SJanusz Dziedzic fftr = (struct phyerr_fft_report *)tlv_buf; 16299702c686SJanusz Dziedzic res = ath10k_dfs_fft_report(ar, event, fftr, tsf); 16309702c686SJanusz Dziedzic if (res) 16319702c686SJanusz Dziedzic return; 16329702c686SJanusz Dziedzic break; 16339702c686SJanusz Dziedzic } 16349702c686SJanusz Dziedzic 16359702c686SJanusz Dziedzic i += sizeof(*tlv) + tlv_len; 16369702c686SJanusz Dziedzic } 16379702c686SJanusz Dziedzic } 16389702c686SJanusz Dziedzic 16399702c686SJanusz Dziedzic static void ath10k_wmi_event_spectral_scan(struct ath10k *ar, 16409702c686SJanusz Dziedzic struct wmi_single_phyerr_rx_event *event, 16419702c686SJanusz Dziedzic u64 tsf) 16429702c686SJanusz Dziedzic { 16439702c686SJanusz Dziedzic ath10k_dbg(ATH10K_DBG_WMI, "wmi event spectral scan\n"); 16449702c686SJanusz Dziedzic } 16459702c686SJanusz Dziedzic 16465e3dd157SKalle Valo static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) 16475e3dd157SKalle Valo { 16489702c686SJanusz Dziedzic struct wmi_comb_phyerr_rx_event *comb_event; 16499702c686SJanusz Dziedzic struct wmi_single_phyerr_rx_event *event; 16509702c686SJanusz Dziedzic u32 count, i, buf_len, phy_err_code; 16519702c686SJanusz Dziedzic u64 tsf; 16529702c686SJanusz Dziedzic int left_len = skb->len; 16539702c686SJanusz Dziedzic 16549702c686SJanusz Dziedzic ATH10K_DFS_STAT_INC(ar, phy_errors); 16559702c686SJanusz Dziedzic 16569702c686SJanusz Dziedzic /* Check if combined event available */ 16579702c686SJanusz Dziedzic if (left_len < sizeof(*comb_event)) { 16589702c686SJanusz Dziedzic ath10k_warn("wmi phyerr combined event wrong len\n"); 16599702c686SJanusz Dziedzic return; 16609702c686SJanusz Dziedzic } 16619702c686SJanusz Dziedzic 16629702c686SJanusz Dziedzic left_len -= sizeof(*comb_event); 16639702c686SJanusz Dziedzic 16649702c686SJanusz Dziedzic /* Check number of included events */ 16659702c686SJanusz Dziedzic comb_event = (struct wmi_comb_phyerr_rx_event *)skb->data; 16669702c686SJanusz Dziedzic count = __le32_to_cpu(comb_event->hdr.num_phyerr_events); 16679702c686SJanusz Dziedzic 16689702c686SJanusz Dziedzic tsf = __le32_to_cpu(comb_event->hdr.tsf_u32); 16699702c686SJanusz Dziedzic tsf <<= 32; 16709702c686SJanusz Dziedzic tsf |= __le32_to_cpu(comb_event->hdr.tsf_l32); 16719702c686SJanusz Dziedzic 16729702c686SJanusz Dziedzic ath10k_dbg(ATH10K_DBG_WMI, 16739702c686SJanusz Dziedzic "wmi event phyerr count %d tsf64 0x%llX\n", 16749702c686SJanusz Dziedzic count, tsf); 16759702c686SJanusz Dziedzic 16769702c686SJanusz Dziedzic event = (struct wmi_single_phyerr_rx_event *)comb_event->bufp; 16779702c686SJanusz Dziedzic for (i = 0; i < count; i++) { 16789702c686SJanusz Dziedzic /* Check if we can read event header */ 16799702c686SJanusz Dziedzic if (left_len < sizeof(*event)) { 16809702c686SJanusz Dziedzic ath10k_warn("single event (%d) wrong head len\n", i); 16819702c686SJanusz Dziedzic return; 16829702c686SJanusz Dziedzic } 16839702c686SJanusz Dziedzic 16849702c686SJanusz Dziedzic left_len -= sizeof(*event); 16859702c686SJanusz Dziedzic 16869702c686SJanusz Dziedzic buf_len = __le32_to_cpu(event->hdr.buf_len); 16879702c686SJanusz Dziedzic phy_err_code = event->hdr.phy_err_code; 16889702c686SJanusz Dziedzic 16899702c686SJanusz Dziedzic if (left_len < buf_len) { 16909702c686SJanusz Dziedzic ath10k_warn("single event (%d) wrong buf len\n", i); 16919702c686SJanusz Dziedzic return; 16929702c686SJanusz Dziedzic } 16939702c686SJanusz Dziedzic 16949702c686SJanusz Dziedzic left_len -= buf_len; 16959702c686SJanusz Dziedzic 16969702c686SJanusz Dziedzic switch (phy_err_code) { 16979702c686SJanusz Dziedzic case PHY_ERROR_RADAR: 16989702c686SJanusz Dziedzic ath10k_wmi_event_dfs(ar, event, tsf); 16999702c686SJanusz Dziedzic break; 17009702c686SJanusz Dziedzic case PHY_ERROR_SPECTRAL_SCAN: 17019702c686SJanusz Dziedzic ath10k_wmi_event_spectral_scan(ar, event, tsf); 17029702c686SJanusz Dziedzic break; 17039702c686SJanusz Dziedzic case PHY_ERROR_FALSE_RADAR_EXT: 17049702c686SJanusz Dziedzic ath10k_wmi_event_dfs(ar, event, tsf); 17059702c686SJanusz Dziedzic ath10k_wmi_event_spectral_scan(ar, event, tsf); 17069702c686SJanusz Dziedzic break; 17079702c686SJanusz Dziedzic default: 17089702c686SJanusz Dziedzic break; 17099702c686SJanusz Dziedzic } 17109702c686SJanusz Dziedzic 17119702c686SJanusz Dziedzic event += sizeof(*event) + buf_len; 17129702c686SJanusz Dziedzic } 17135e3dd157SKalle Valo } 17145e3dd157SKalle Valo 17155e3dd157SKalle Valo static void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb) 17165e3dd157SKalle Valo { 17175e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_ROAM_EVENTID\n"); 17185e3dd157SKalle Valo } 17195e3dd157SKalle Valo 17205e3dd157SKalle Valo static void ath10k_wmi_event_profile_match(struct ath10k *ar, 17215e3dd157SKalle Valo struct sk_buff *skb) 17225e3dd157SKalle Valo { 17235e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_PROFILE_MATCH\n"); 17245e3dd157SKalle Valo } 17255e3dd157SKalle Valo 17265e3dd157SKalle Valo static void ath10k_wmi_event_debug_print(struct ath10k *ar, 17275e3dd157SKalle Valo struct sk_buff *skb) 17285e3dd157SKalle Valo { 17292fe5288cSKalle Valo char buf[101], c; 17302fe5288cSKalle Valo int i; 17312fe5288cSKalle Valo 17322fe5288cSKalle Valo for (i = 0; i < sizeof(buf) - 1; i++) { 17332fe5288cSKalle Valo if (i >= skb->len) 17342fe5288cSKalle Valo break; 17352fe5288cSKalle Valo 17362fe5288cSKalle Valo c = skb->data[i]; 17372fe5288cSKalle Valo 17382fe5288cSKalle Valo if (c == '\0') 17392fe5288cSKalle Valo break; 17402fe5288cSKalle Valo 17412fe5288cSKalle Valo if (isascii(c) && isprint(c)) 17422fe5288cSKalle Valo buf[i] = c; 17432fe5288cSKalle Valo else 17442fe5288cSKalle Valo buf[i] = '.'; 17452fe5288cSKalle Valo } 17462fe5288cSKalle Valo 17472fe5288cSKalle Valo if (i == sizeof(buf) - 1) 17482fe5288cSKalle Valo ath10k_warn("wmi debug print truncated: %d\n", skb->len); 17492fe5288cSKalle Valo 17502fe5288cSKalle Valo /* for some reason the debug prints end with \n, remove that */ 17512fe5288cSKalle Valo if (skb->data[i - 1] == '\n') 17522fe5288cSKalle Valo i--; 17532fe5288cSKalle Valo 17542fe5288cSKalle Valo /* the last byte is always reserved for the null character */ 17552fe5288cSKalle Valo buf[i] = '\0'; 17562fe5288cSKalle Valo 17572fe5288cSKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi event debug print '%s'\n", buf); 17585e3dd157SKalle Valo } 17595e3dd157SKalle Valo 17605e3dd157SKalle Valo static void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb) 17615e3dd157SKalle Valo { 17625e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_PDEV_QVIT_EVENTID\n"); 17635e3dd157SKalle Valo } 17645e3dd157SKalle Valo 17655e3dd157SKalle Valo static void ath10k_wmi_event_wlan_profile_data(struct ath10k *ar, 17665e3dd157SKalle Valo struct sk_buff *skb) 17675e3dd157SKalle Valo { 17685e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_WLAN_PROFILE_DATA_EVENTID\n"); 17695e3dd157SKalle Valo } 17705e3dd157SKalle Valo 17715e3dd157SKalle Valo static void ath10k_wmi_event_rtt_measurement_report(struct ath10k *ar, 17725e3dd157SKalle Valo struct sk_buff *skb) 17735e3dd157SKalle Valo { 17745e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_RTT_MEASUREMENT_REPORT_EVENTID\n"); 17755e3dd157SKalle Valo } 17765e3dd157SKalle Valo 17775e3dd157SKalle Valo static void ath10k_wmi_event_tsf_measurement_report(struct ath10k *ar, 17785e3dd157SKalle Valo struct sk_buff *skb) 17795e3dd157SKalle Valo { 17805e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_TSF_MEASUREMENT_REPORT_EVENTID\n"); 17815e3dd157SKalle Valo } 17825e3dd157SKalle Valo 17835e3dd157SKalle Valo static void ath10k_wmi_event_rtt_error_report(struct ath10k *ar, 17845e3dd157SKalle Valo struct sk_buff *skb) 17855e3dd157SKalle Valo { 17865e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_RTT_ERROR_REPORT_EVENTID\n"); 17875e3dd157SKalle Valo } 17885e3dd157SKalle Valo 17895e3dd157SKalle Valo static void ath10k_wmi_event_wow_wakeup_host(struct ath10k *ar, 17905e3dd157SKalle Valo struct sk_buff *skb) 17915e3dd157SKalle Valo { 17925e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_WOW_WAKEUP_HOST_EVENTID\n"); 17935e3dd157SKalle Valo } 17945e3dd157SKalle Valo 17955e3dd157SKalle Valo static void ath10k_wmi_event_dcs_interference(struct ath10k *ar, 17965e3dd157SKalle Valo struct sk_buff *skb) 17975e3dd157SKalle Valo { 17985e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_DCS_INTERFERENCE_EVENTID\n"); 17995e3dd157SKalle Valo } 18005e3dd157SKalle Valo 18015e3dd157SKalle Valo static void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, 18025e3dd157SKalle Valo struct sk_buff *skb) 18035e3dd157SKalle Valo { 18045e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_PDEV_TPC_CONFIG_EVENTID\n"); 18055e3dd157SKalle Valo } 18065e3dd157SKalle Valo 18075e3dd157SKalle Valo static void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, 18085e3dd157SKalle Valo struct sk_buff *skb) 18095e3dd157SKalle Valo { 18105e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_PDEV_FTM_INTG_EVENTID\n"); 18115e3dd157SKalle Valo } 18125e3dd157SKalle Valo 18135e3dd157SKalle Valo static void ath10k_wmi_event_gtk_offload_status(struct ath10k *ar, 18145e3dd157SKalle Valo struct sk_buff *skb) 18155e3dd157SKalle Valo { 18165e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_GTK_OFFLOAD_STATUS_EVENTID\n"); 18175e3dd157SKalle Valo } 18185e3dd157SKalle Valo 18195e3dd157SKalle Valo static void ath10k_wmi_event_gtk_rekey_fail(struct ath10k *ar, 18205e3dd157SKalle Valo struct sk_buff *skb) 18215e3dd157SKalle Valo { 18225e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_GTK_REKEY_FAIL_EVENTID\n"); 18235e3dd157SKalle Valo } 18245e3dd157SKalle Valo 18255e3dd157SKalle Valo static void ath10k_wmi_event_delba_complete(struct ath10k *ar, 18265e3dd157SKalle Valo struct sk_buff *skb) 18275e3dd157SKalle Valo { 18285e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_TX_DELBA_COMPLETE_EVENTID\n"); 18295e3dd157SKalle Valo } 18305e3dd157SKalle Valo 18315e3dd157SKalle Valo static void ath10k_wmi_event_addba_complete(struct ath10k *ar, 18325e3dd157SKalle Valo struct sk_buff *skb) 18335e3dd157SKalle Valo { 18345e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_TX_ADDBA_COMPLETE_EVENTID\n"); 18355e3dd157SKalle Valo } 18365e3dd157SKalle Valo 18375e3dd157SKalle Valo static void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar, 18385e3dd157SKalle Valo struct sk_buff *skb) 18395e3dd157SKalle Valo { 18405e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n"); 18415e3dd157SKalle Valo } 18425e3dd157SKalle Valo 18438a6618b0SBartosz Markowski static void ath10k_wmi_event_inst_rssi_stats(struct ath10k *ar, 18448a6618b0SBartosz Markowski struct sk_buff *skb) 18458a6618b0SBartosz Markowski { 18468a6618b0SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "WMI_INST_RSSI_STATS_EVENTID\n"); 18478a6618b0SBartosz Markowski } 18488a6618b0SBartosz Markowski 18498a6618b0SBartosz Markowski static void ath10k_wmi_event_vdev_standby_req(struct ath10k *ar, 18508a6618b0SBartosz Markowski struct sk_buff *skb) 18518a6618b0SBartosz Markowski { 18528a6618b0SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_STANDBY_REQ_EVENTID\n"); 18538a6618b0SBartosz Markowski } 18548a6618b0SBartosz Markowski 18558a6618b0SBartosz Markowski static void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar, 18568a6618b0SBartosz Markowski struct sk_buff *skb) 18578a6618b0SBartosz Markowski { 18588a6618b0SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_RESUME_REQ_EVENTID\n"); 18598a6618b0SBartosz Markowski } 18608a6618b0SBartosz Markowski 1861b3effe61SBartosz Markowski static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id, 1862b3effe61SBartosz Markowski u32 num_units, u32 unit_len) 1863b3effe61SBartosz Markowski { 1864b3effe61SBartosz Markowski dma_addr_t paddr; 1865b3effe61SBartosz Markowski u32 pool_size; 1866b3effe61SBartosz Markowski int idx = ar->wmi.num_mem_chunks; 1867b3effe61SBartosz Markowski 1868b3effe61SBartosz Markowski pool_size = num_units * round_up(unit_len, 4); 1869b3effe61SBartosz Markowski 1870b3effe61SBartosz Markowski if (!pool_size) 1871b3effe61SBartosz Markowski return -EINVAL; 1872b3effe61SBartosz Markowski 1873b3effe61SBartosz Markowski ar->wmi.mem_chunks[idx].vaddr = dma_alloc_coherent(ar->dev, 1874b3effe61SBartosz Markowski pool_size, 1875b3effe61SBartosz Markowski &paddr, 1876b3effe61SBartosz Markowski GFP_ATOMIC); 1877b3effe61SBartosz Markowski if (!ar->wmi.mem_chunks[idx].vaddr) { 1878b3effe61SBartosz Markowski ath10k_warn("failed to allocate memory chunk\n"); 1879b3effe61SBartosz Markowski return -ENOMEM; 1880b3effe61SBartosz Markowski } 1881b3effe61SBartosz Markowski 1882b3effe61SBartosz Markowski memset(ar->wmi.mem_chunks[idx].vaddr, 0, pool_size); 1883b3effe61SBartosz Markowski 1884b3effe61SBartosz Markowski ar->wmi.mem_chunks[idx].paddr = paddr; 1885b3effe61SBartosz Markowski ar->wmi.mem_chunks[idx].len = pool_size; 1886b3effe61SBartosz Markowski ar->wmi.mem_chunks[idx].req_id = req_id; 1887b3effe61SBartosz Markowski ar->wmi.num_mem_chunks++; 1888b3effe61SBartosz Markowski 1889b3effe61SBartosz Markowski return 0; 1890b3effe61SBartosz Markowski } 1891b3effe61SBartosz Markowski 18925e3dd157SKalle Valo static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, 18935e3dd157SKalle Valo struct sk_buff *skb) 18945e3dd157SKalle Valo { 18955e3dd157SKalle Valo struct wmi_service_ready_event *ev = (void *)skb->data; 18965e3dd157SKalle Valo 18975e3dd157SKalle Valo if (skb->len < sizeof(*ev)) { 18985e3dd157SKalle Valo ath10k_warn("Service ready event was %d B but expected %zu B. Wrong firmware version?\n", 18995e3dd157SKalle Valo skb->len, sizeof(*ev)); 19005e3dd157SKalle Valo return; 19015e3dd157SKalle Valo } 19025e3dd157SKalle Valo 19035e3dd157SKalle Valo ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power); 19045e3dd157SKalle Valo ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power); 19055e3dd157SKalle Valo ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info); 19065e3dd157SKalle Valo ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info); 19075e3dd157SKalle Valo ar->fw_version_major = 19085e3dd157SKalle Valo (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24; 19095e3dd157SKalle Valo ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff); 19105e3dd157SKalle Valo ar->fw_version_release = 19115e3dd157SKalle Valo (__le32_to_cpu(ev->sw_version_1) & 0xffff0000) >> 16; 19125e3dd157SKalle Valo ar->fw_version_build = (__le32_to_cpu(ev->sw_version_1) & 0x0000ffff); 19135e3dd157SKalle Valo ar->phy_capability = __le32_to_cpu(ev->phy_capability); 19148865bee4SMichal Kazior ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); 19158865bee4SMichal Kazior 19161a222435SKalle Valo /* only manually set fw features when not using FW IE format */ 19171a222435SKalle Valo if (ar->fw_api == 1 && ar->fw_version_build > 636) 19180d9b0438SMichal Kazior set_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features); 19190d9b0438SMichal Kazior 19208865bee4SMichal Kazior if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) { 19218865bee4SMichal Kazior ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n", 19228865bee4SMichal Kazior ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM); 19238865bee4SMichal Kazior ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM; 19248865bee4SMichal Kazior } 19255e3dd157SKalle Valo 19265e3dd157SKalle Valo ar->ath_common.regulatory.current_rd = 19275e3dd157SKalle Valo __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd); 19285e3dd157SKalle Valo 19295e3dd157SKalle Valo ath10k_debug_read_service_map(ar, ev->wmi_service_bitmap, 19305e3dd157SKalle Valo sizeof(ev->wmi_service_bitmap)); 19315e3dd157SKalle Valo 19325e3dd157SKalle Valo if (strlen(ar->hw->wiphy->fw_version) == 0) { 19335e3dd157SKalle Valo snprintf(ar->hw->wiphy->fw_version, 19345e3dd157SKalle Valo sizeof(ar->hw->wiphy->fw_version), 19355e3dd157SKalle Valo "%u.%u.%u.%u", 19365e3dd157SKalle Valo ar->fw_version_major, 19375e3dd157SKalle Valo ar->fw_version_minor, 19385e3dd157SKalle Valo ar->fw_version_release, 19395e3dd157SKalle Valo ar->fw_version_build); 19405e3dd157SKalle Valo } 19415e3dd157SKalle Valo 19425e3dd157SKalle Valo /* FIXME: it probably should be better to support this */ 19435e3dd157SKalle Valo if (__le32_to_cpu(ev->num_mem_reqs) > 0) { 19445e3dd157SKalle Valo ath10k_warn("target requested %d memory chunks; ignoring\n", 19455e3dd157SKalle Valo __le32_to_cpu(ev->num_mem_reqs)); 19465e3dd157SKalle Valo } 19475e3dd157SKalle Valo 19485e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 19498865bee4SMichal Kazior "wmi event service ready sw_ver 0x%08x sw_ver1 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n", 19505e3dd157SKalle Valo __le32_to_cpu(ev->sw_version), 19515e3dd157SKalle Valo __le32_to_cpu(ev->sw_version_1), 19525e3dd157SKalle Valo __le32_to_cpu(ev->abi_version), 19535e3dd157SKalle Valo __le32_to_cpu(ev->phy_capability), 19545e3dd157SKalle Valo __le32_to_cpu(ev->ht_cap_info), 19555e3dd157SKalle Valo __le32_to_cpu(ev->vht_cap_info), 19565e3dd157SKalle Valo __le32_to_cpu(ev->vht_supp_mcs), 19575e3dd157SKalle Valo __le32_to_cpu(ev->sys_cap_info), 19588865bee4SMichal Kazior __le32_to_cpu(ev->num_mem_reqs), 19598865bee4SMichal Kazior __le32_to_cpu(ev->num_rf_chains)); 19605e3dd157SKalle Valo 19615e3dd157SKalle Valo complete(&ar->wmi.service_ready); 19625e3dd157SKalle Valo } 19635e3dd157SKalle Valo 19646f97d256SBartosz Markowski static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar, 19656f97d256SBartosz Markowski struct sk_buff *skb) 19666f97d256SBartosz Markowski { 1967b3effe61SBartosz Markowski u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i; 1968b3effe61SBartosz Markowski int ret; 19696f97d256SBartosz Markowski struct wmi_service_ready_event_10x *ev = (void *)skb->data; 19706f97d256SBartosz Markowski 19716f97d256SBartosz Markowski if (skb->len < sizeof(*ev)) { 19726f97d256SBartosz Markowski ath10k_warn("Service ready event was %d B but expected %zu B. Wrong firmware version?\n", 19736f97d256SBartosz Markowski skb->len, sizeof(*ev)); 19746f97d256SBartosz Markowski return; 19756f97d256SBartosz Markowski } 19766f97d256SBartosz Markowski 19776f97d256SBartosz Markowski ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power); 19786f97d256SBartosz Markowski ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power); 19796f97d256SBartosz Markowski ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info); 19806f97d256SBartosz Markowski ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info); 19816f97d256SBartosz Markowski ar->fw_version_major = 19826f97d256SBartosz Markowski (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24; 19836f97d256SBartosz Markowski ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff); 19846f97d256SBartosz Markowski ar->phy_capability = __le32_to_cpu(ev->phy_capability); 19856f97d256SBartosz Markowski ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); 19866f97d256SBartosz Markowski 19876f97d256SBartosz Markowski if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) { 19886f97d256SBartosz Markowski ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n", 19896f97d256SBartosz Markowski ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM); 19906f97d256SBartosz Markowski ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM; 19916f97d256SBartosz Markowski } 19926f97d256SBartosz Markowski 19936f97d256SBartosz Markowski ar->ath_common.regulatory.current_rd = 19946f97d256SBartosz Markowski __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd); 19956f97d256SBartosz Markowski 19966f97d256SBartosz Markowski ath10k_debug_read_service_map(ar, ev->wmi_service_bitmap, 19976f97d256SBartosz Markowski sizeof(ev->wmi_service_bitmap)); 19986f97d256SBartosz Markowski 19996f97d256SBartosz Markowski if (strlen(ar->hw->wiphy->fw_version) == 0) { 20006f97d256SBartosz Markowski snprintf(ar->hw->wiphy->fw_version, 20016f97d256SBartosz Markowski sizeof(ar->hw->wiphy->fw_version), 20026f97d256SBartosz Markowski "%u.%u", 20036f97d256SBartosz Markowski ar->fw_version_major, 20046f97d256SBartosz Markowski ar->fw_version_minor); 20056f97d256SBartosz Markowski } 20066f97d256SBartosz Markowski 2007b3effe61SBartosz Markowski num_mem_reqs = __le32_to_cpu(ev->num_mem_reqs); 2008b3effe61SBartosz Markowski 2009b3effe61SBartosz Markowski if (num_mem_reqs > ATH10K_MAX_MEM_REQS) { 2010b3effe61SBartosz Markowski ath10k_warn("requested memory chunks number (%d) exceeds the limit\n", 2011b3effe61SBartosz Markowski num_mem_reqs); 2012b3effe61SBartosz Markowski return; 20136f97d256SBartosz Markowski } 20146f97d256SBartosz Markowski 2015b3effe61SBartosz Markowski if (!num_mem_reqs) 2016b3effe61SBartosz Markowski goto exit; 2017b3effe61SBartosz Markowski 2018b3effe61SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "firmware has requested %d memory chunks\n", 2019b3effe61SBartosz Markowski num_mem_reqs); 2020b3effe61SBartosz Markowski 2021b3effe61SBartosz Markowski for (i = 0; i < num_mem_reqs; ++i) { 2022b3effe61SBartosz Markowski req_id = __le32_to_cpu(ev->mem_reqs[i].req_id); 2023b3effe61SBartosz Markowski num_units = __le32_to_cpu(ev->mem_reqs[i].num_units); 2024b3effe61SBartosz Markowski unit_size = __le32_to_cpu(ev->mem_reqs[i].unit_size); 2025b3effe61SBartosz Markowski num_unit_info = __le32_to_cpu(ev->mem_reqs[i].num_unit_info); 2026b3effe61SBartosz Markowski 2027b3effe61SBartosz Markowski if (num_unit_info & NUM_UNITS_IS_NUM_PEERS) 2028b3effe61SBartosz Markowski /* number of units to allocate is number of 2029b3effe61SBartosz Markowski * peers, 1 extra for self peer on target */ 2030b3effe61SBartosz Markowski /* this needs to be tied, host and target 2031b3effe61SBartosz Markowski * can get out of sync */ 2032ec6a73f0SBartosz Markowski num_units = TARGET_10X_NUM_PEERS + 1; 2033b3effe61SBartosz Markowski else if (num_unit_info & NUM_UNITS_IS_NUM_VDEVS) 2034ec6a73f0SBartosz Markowski num_units = TARGET_10X_NUM_VDEVS + 1; 2035b3effe61SBartosz Markowski 2036b3effe61SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, 2037b3effe61SBartosz Markowski "wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n", 2038b3effe61SBartosz Markowski req_id, 2039b3effe61SBartosz Markowski __le32_to_cpu(ev->mem_reqs[i].num_units), 2040b3effe61SBartosz Markowski num_unit_info, 2041b3effe61SBartosz Markowski unit_size, 2042b3effe61SBartosz Markowski num_units); 2043b3effe61SBartosz Markowski 2044b3effe61SBartosz Markowski ret = ath10k_wmi_alloc_host_mem(ar, req_id, num_units, 2045b3effe61SBartosz Markowski unit_size); 2046b3effe61SBartosz Markowski if (ret) 2047b3effe61SBartosz Markowski return; 2048b3effe61SBartosz Markowski } 2049b3effe61SBartosz Markowski 2050b3effe61SBartosz Markowski exit: 20516f97d256SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, 20526f97d256SBartosz Markowski "wmi event service ready sw_ver 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n", 20536f97d256SBartosz Markowski __le32_to_cpu(ev->sw_version), 20546f97d256SBartosz Markowski __le32_to_cpu(ev->abi_version), 20556f97d256SBartosz Markowski __le32_to_cpu(ev->phy_capability), 20566f97d256SBartosz Markowski __le32_to_cpu(ev->ht_cap_info), 20576f97d256SBartosz Markowski __le32_to_cpu(ev->vht_cap_info), 20586f97d256SBartosz Markowski __le32_to_cpu(ev->vht_supp_mcs), 20596f97d256SBartosz Markowski __le32_to_cpu(ev->sys_cap_info), 20606f97d256SBartosz Markowski __le32_to_cpu(ev->num_mem_reqs), 20616f97d256SBartosz Markowski __le32_to_cpu(ev->num_rf_chains)); 20626f97d256SBartosz Markowski 20636f97d256SBartosz Markowski complete(&ar->wmi.service_ready); 20646f97d256SBartosz Markowski } 20656f97d256SBartosz Markowski 20665e3dd157SKalle Valo static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) 20675e3dd157SKalle Valo { 20685e3dd157SKalle Valo struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data; 20695e3dd157SKalle Valo 20705e3dd157SKalle Valo if (WARN_ON(skb->len < sizeof(*ev))) 20715e3dd157SKalle Valo return -EINVAL; 20725e3dd157SKalle Valo 20735e3dd157SKalle Valo memcpy(ar->mac_addr, ev->mac_addr.addr, ETH_ALEN); 20745e3dd157SKalle Valo 20755e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 20765e3dd157SKalle Valo "wmi event ready sw_version %u abi_version %u mac_addr %pM status %d\n", 20775e3dd157SKalle Valo __le32_to_cpu(ev->sw_version), 20785e3dd157SKalle Valo __le32_to_cpu(ev->abi_version), 20795e3dd157SKalle Valo ev->mac_addr.addr, 20805e3dd157SKalle Valo __le32_to_cpu(ev->status)); 20815e3dd157SKalle Valo 20825e3dd157SKalle Valo complete(&ar->wmi.unified_ready); 20835e3dd157SKalle Valo return 0; 20845e3dd157SKalle Valo } 20855e3dd157SKalle Valo 2086ce42870eSBartosz Markowski static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb) 20875e3dd157SKalle Valo { 20885e3dd157SKalle Valo struct wmi_cmd_hdr *cmd_hdr; 20895e3dd157SKalle Valo enum wmi_event_id id; 20905e3dd157SKalle Valo u16 len; 20915e3dd157SKalle Valo 20925e3dd157SKalle Valo cmd_hdr = (struct wmi_cmd_hdr *)skb->data; 20935e3dd157SKalle Valo id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); 20945e3dd157SKalle Valo 20955e3dd157SKalle Valo if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) 20965e3dd157SKalle Valo return; 20975e3dd157SKalle Valo 20985e3dd157SKalle Valo len = skb->len; 20995e3dd157SKalle Valo 21005e3dd157SKalle Valo trace_ath10k_wmi_event(id, skb->data, skb->len); 21015e3dd157SKalle Valo 21025e3dd157SKalle Valo switch (id) { 21035e3dd157SKalle Valo case WMI_MGMT_RX_EVENTID: 21045e3dd157SKalle Valo ath10k_wmi_event_mgmt_rx(ar, skb); 21055e3dd157SKalle Valo /* mgmt_rx() owns the skb now! */ 21065e3dd157SKalle Valo return; 21075e3dd157SKalle Valo case WMI_SCAN_EVENTID: 21085e3dd157SKalle Valo ath10k_wmi_event_scan(ar, skb); 21095e3dd157SKalle Valo break; 21105e3dd157SKalle Valo case WMI_CHAN_INFO_EVENTID: 21115e3dd157SKalle Valo ath10k_wmi_event_chan_info(ar, skb); 21125e3dd157SKalle Valo break; 21135e3dd157SKalle Valo case WMI_ECHO_EVENTID: 21145e3dd157SKalle Valo ath10k_wmi_event_echo(ar, skb); 21155e3dd157SKalle Valo break; 21165e3dd157SKalle Valo case WMI_DEBUG_MESG_EVENTID: 21175e3dd157SKalle Valo ath10k_wmi_event_debug_mesg(ar, skb); 21185e3dd157SKalle Valo break; 21195e3dd157SKalle Valo case WMI_UPDATE_STATS_EVENTID: 21205e3dd157SKalle Valo ath10k_wmi_event_update_stats(ar, skb); 21215e3dd157SKalle Valo break; 21225e3dd157SKalle Valo case WMI_VDEV_START_RESP_EVENTID: 21235e3dd157SKalle Valo ath10k_wmi_event_vdev_start_resp(ar, skb); 21245e3dd157SKalle Valo break; 21255e3dd157SKalle Valo case WMI_VDEV_STOPPED_EVENTID: 21265e3dd157SKalle Valo ath10k_wmi_event_vdev_stopped(ar, skb); 21275e3dd157SKalle Valo break; 21285e3dd157SKalle Valo case WMI_PEER_STA_KICKOUT_EVENTID: 21295e3dd157SKalle Valo ath10k_wmi_event_peer_sta_kickout(ar, skb); 21305e3dd157SKalle Valo break; 21315e3dd157SKalle Valo case WMI_HOST_SWBA_EVENTID: 21325e3dd157SKalle Valo ath10k_wmi_event_host_swba(ar, skb); 21335e3dd157SKalle Valo break; 21345e3dd157SKalle Valo case WMI_TBTTOFFSET_UPDATE_EVENTID: 21355e3dd157SKalle Valo ath10k_wmi_event_tbttoffset_update(ar, skb); 21365e3dd157SKalle Valo break; 21375e3dd157SKalle Valo case WMI_PHYERR_EVENTID: 21385e3dd157SKalle Valo ath10k_wmi_event_phyerr(ar, skb); 21395e3dd157SKalle Valo break; 21405e3dd157SKalle Valo case WMI_ROAM_EVENTID: 21415e3dd157SKalle Valo ath10k_wmi_event_roam(ar, skb); 21425e3dd157SKalle Valo break; 21435e3dd157SKalle Valo case WMI_PROFILE_MATCH: 21445e3dd157SKalle Valo ath10k_wmi_event_profile_match(ar, skb); 21455e3dd157SKalle Valo break; 21465e3dd157SKalle Valo case WMI_DEBUG_PRINT_EVENTID: 21475e3dd157SKalle Valo ath10k_wmi_event_debug_print(ar, skb); 21485e3dd157SKalle Valo break; 21495e3dd157SKalle Valo case WMI_PDEV_QVIT_EVENTID: 21505e3dd157SKalle Valo ath10k_wmi_event_pdev_qvit(ar, skb); 21515e3dd157SKalle Valo break; 21525e3dd157SKalle Valo case WMI_WLAN_PROFILE_DATA_EVENTID: 21535e3dd157SKalle Valo ath10k_wmi_event_wlan_profile_data(ar, skb); 21545e3dd157SKalle Valo break; 21555e3dd157SKalle Valo case WMI_RTT_MEASUREMENT_REPORT_EVENTID: 21565e3dd157SKalle Valo ath10k_wmi_event_rtt_measurement_report(ar, skb); 21575e3dd157SKalle Valo break; 21585e3dd157SKalle Valo case WMI_TSF_MEASUREMENT_REPORT_EVENTID: 21595e3dd157SKalle Valo ath10k_wmi_event_tsf_measurement_report(ar, skb); 21605e3dd157SKalle Valo break; 21615e3dd157SKalle Valo case WMI_RTT_ERROR_REPORT_EVENTID: 21625e3dd157SKalle Valo ath10k_wmi_event_rtt_error_report(ar, skb); 21635e3dd157SKalle Valo break; 21645e3dd157SKalle Valo case WMI_WOW_WAKEUP_HOST_EVENTID: 21655e3dd157SKalle Valo ath10k_wmi_event_wow_wakeup_host(ar, skb); 21665e3dd157SKalle Valo break; 21675e3dd157SKalle Valo case WMI_DCS_INTERFERENCE_EVENTID: 21685e3dd157SKalle Valo ath10k_wmi_event_dcs_interference(ar, skb); 21695e3dd157SKalle Valo break; 21705e3dd157SKalle Valo case WMI_PDEV_TPC_CONFIG_EVENTID: 21715e3dd157SKalle Valo ath10k_wmi_event_pdev_tpc_config(ar, skb); 21725e3dd157SKalle Valo break; 21735e3dd157SKalle Valo case WMI_PDEV_FTM_INTG_EVENTID: 21745e3dd157SKalle Valo ath10k_wmi_event_pdev_ftm_intg(ar, skb); 21755e3dd157SKalle Valo break; 21765e3dd157SKalle Valo case WMI_GTK_OFFLOAD_STATUS_EVENTID: 21775e3dd157SKalle Valo ath10k_wmi_event_gtk_offload_status(ar, skb); 21785e3dd157SKalle Valo break; 21795e3dd157SKalle Valo case WMI_GTK_REKEY_FAIL_EVENTID: 21805e3dd157SKalle Valo ath10k_wmi_event_gtk_rekey_fail(ar, skb); 21815e3dd157SKalle Valo break; 21825e3dd157SKalle Valo case WMI_TX_DELBA_COMPLETE_EVENTID: 21835e3dd157SKalle Valo ath10k_wmi_event_delba_complete(ar, skb); 21845e3dd157SKalle Valo break; 21855e3dd157SKalle Valo case WMI_TX_ADDBA_COMPLETE_EVENTID: 21865e3dd157SKalle Valo ath10k_wmi_event_addba_complete(ar, skb); 21875e3dd157SKalle Valo break; 21885e3dd157SKalle Valo case WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID: 21895e3dd157SKalle Valo ath10k_wmi_event_vdev_install_key_complete(ar, skb); 21905e3dd157SKalle Valo break; 21915e3dd157SKalle Valo case WMI_SERVICE_READY_EVENTID: 21925e3dd157SKalle Valo ath10k_wmi_service_ready_event_rx(ar, skb); 21935e3dd157SKalle Valo break; 21945e3dd157SKalle Valo case WMI_READY_EVENTID: 21955e3dd157SKalle Valo ath10k_wmi_ready_event_rx(ar, skb); 21965e3dd157SKalle Valo break; 21975e3dd157SKalle Valo default: 21985e3dd157SKalle Valo ath10k_warn("Unknown eventid: %d\n", id); 21995e3dd157SKalle Valo break; 22005e3dd157SKalle Valo } 22015e3dd157SKalle Valo 22025e3dd157SKalle Valo dev_kfree_skb(skb); 22035e3dd157SKalle Valo } 22045e3dd157SKalle Valo 22058a6618b0SBartosz Markowski static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) 22068a6618b0SBartosz Markowski { 22078a6618b0SBartosz Markowski struct wmi_cmd_hdr *cmd_hdr; 22088a6618b0SBartosz Markowski enum wmi_10x_event_id id; 22098a6618b0SBartosz Markowski u16 len; 22108a6618b0SBartosz Markowski 22118a6618b0SBartosz Markowski cmd_hdr = (struct wmi_cmd_hdr *)skb->data; 22128a6618b0SBartosz Markowski id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); 22138a6618b0SBartosz Markowski 22148a6618b0SBartosz Markowski if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) 22158a6618b0SBartosz Markowski return; 22168a6618b0SBartosz Markowski 22178a6618b0SBartosz Markowski len = skb->len; 22188a6618b0SBartosz Markowski 22198a6618b0SBartosz Markowski trace_ath10k_wmi_event(id, skb->data, skb->len); 22208a6618b0SBartosz Markowski 22218a6618b0SBartosz Markowski switch (id) { 22228a6618b0SBartosz Markowski case WMI_10X_MGMT_RX_EVENTID: 22238a6618b0SBartosz Markowski ath10k_wmi_event_mgmt_rx(ar, skb); 22248a6618b0SBartosz Markowski /* mgmt_rx() owns the skb now! */ 22258a6618b0SBartosz Markowski return; 22268a6618b0SBartosz Markowski case WMI_10X_SCAN_EVENTID: 22278a6618b0SBartosz Markowski ath10k_wmi_event_scan(ar, skb); 22288a6618b0SBartosz Markowski break; 22298a6618b0SBartosz Markowski case WMI_10X_CHAN_INFO_EVENTID: 22308a6618b0SBartosz Markowski ath10k_wmi_event_chan_info(ar, skb); 22318a6618b0SBartosz Markowski break; 22328a6618b0SBartosz Markowski case WMI_10X_ECHO_EVENTID: 22338a6618b0SBartosz Markowski ath10k_wmi_event_echo(ar, skb); 22348a6618b0SBartosz Markowski break; 22358a6618b0SBartosz Markowski case WMI_10X_DEBUG_MESG_EVENTID: 22368a6618b0SBartosz Markowski ath10k_wmi_event_debug_mesg(ar, skb); 22378a6618b0SBartosz Markowski break; 22388a6618b0SBartosz Markowski case WMI_10X_UPDATE_STATS_EVENTID: 22398a6618b0SBartosz Markowski ath10k_wmi_event_update_stats(ar, skb); 22408a6618b0SBartosz Markowski break; 22418a6618b0SBartosz Markowski case WMI_10X_VDEV_START_RESP_EVENTID: 22428a6618b0SBartosz Markowski ath10k_wmi_event_vdev_start_resp(ar, skb); 22438a6618b0SBartosz Markowski break; 22448a6618b0SBartosz Markowski case WMI_10X_VDEV_STOPPED_EVENTID: 22458a6618b0SBartosz Markowski ath10k_wmi_event_vdev_stopped(ar, skb); 22468a6618b0SBartosz Markowski break; 22478a6618b0SBartosz Markowski case WMI_10X_PEER_STA_KICKOUT_EVENTID: 22488a6618b0SBartosz Markowski ath10k_wmi_event_peer_sta_kickout(ar, skb); 22498a6618b0SBartosz Markowski break; 22508a6618b0SBartosz Markowski case WMI_10X_HOST_SWBA_EVENTID: 22518a6618b0SBartosz Markowski ath10k_wmi_event_host_swba(ar, skb); 22528a6618b0SBartosz Markowski break; 22538a6618b0SBartosz Markowski case WMI_10X_TBTTOFFSET_UPDATE_EVENTID: 22548a6618b0SBartosz Markowski ath10k_wmi_event_tbttoffset_update(ar, skb); 22558a6618b0SBartosz Markowski break; 22568a6618b0SBartosz Markowski case WMI_10X_PHYERR_EVENTID: 22578a6618b0SBartosz Markowski ath10k_wmi_event_phyerr(ar, skb); 22588a6618b0SBartosz Markowski break; 22598a6618b0SBartosz Markowski case WMI_10X_ROAM_EVENTID: 22608a6618b0SBartosz Markowski ath10k_wmi_event_roam(ar, skb); 22618a6618b0SBartosz Markowski break; 22628a6618b0SBartosz Markowski case WMI_10X_PROFILE_MATCH: 22638a6618b0SBartosz Markowski ath10k_wmi_event_profile_match(ar, skb); 22648a6618b0SBartosz Markowski break; 22658a6618b0SBartosz Markowski case WMI_10X_DEBUG_PRINT_EVENTID: 22668a6618b0SBartosz Markowski ath10k_wmi_event_debug_print(ar, skb); 22678a6618b0SBartosz Markowski break; 22688a6618b0SBartosz Markowski case WMI_10X_PDEV_QVIT_EVENTID: 22698a6618b0SBartosz Markowski ath10k_wmi_event_pdev_qvit(ar, skb); 22708a6618b0SBartosz Markowski break; 22718a6618b0SBartosz Markowski case WMI_10X_WLAN_PROFILE_DATA_EVENTID: 22728a6618b0SBartosz Markowski ath10k_wmi_event_wlan_profile_data(ar, skb); 22738a6618b0SBartosz Markowski break; 22748a6618b0SBartosz Markowski case WMI_10X_RTT_MEASUREMENT_REPORT_EVENTID: 22758a6618b0SBartosz Markowski ath10k_wmi_event_rtt_measurement_report(ar, skb); 22768a6618b0SBartosz Markowski break; 22778a6618b0SBartosz Markowski case WMI_10X_TSF_MEASUREMENT_REPORT_EVENTID: 22788a6618b0SBartosz Markowski ath10k_wmi_event_tsf_measurement_report(ar, skb); 22798a6618b0SBartosz Markowski break; 22808a6618b0SBartosz Markowski case WMI_10X_RTT_ERROR_REPORT_EVENTID: 22818a6618b0SBartosz Markowski ath10k_wmi_event_rtt_error_report(ar, skb); 22828a6618b0SBartosz Markowski break; 22838a6618b0SBartosz Markowski case WMI_10X_WOW_WAKEUP_HOST_EVENTID: 22848a6618b0SBartosz Markowski ath10k_wmi_event_wow_wakeup_host(ar, skb); 22858a6618b0SBartosz Markowski break; 22868a6618b0SBartosz Markowski case WMI_10X_DCS_INTERFERENCE_EVENTID: 22878a6618b0SBartosz Markowski ath10k_wmi_event_dcs_interference(ar, skb); 22888a6618b0SBartosz Markowski break; 22898a6618b0SBartosz Markowski case WMI_10X_PDEV_TPC_CONFIG_EVENTID: 22908a6618b0SBartosz Markowski ath10k_wmi_event_pdev_tpc_config(ar, skb); 22918a6618b0SBartosz Markowski break; 22928a6618b0SBartosz Markowski case WMI_10X_INST_RSSI_STATS_EVENTID: 22938a6618b0SBartosz Markowski ath10k_wmi_event_inst_rssi_stats(ar, skb); 22948a6618b0SBartosz Markowski break; 22958a6618b0SBartosz Markowski case WMI_10X_VDEV_STANDBY_REQ_EVENTID: 22968a6618b0SBartosz Markowski ath10k_wmi_event_vdev_standby_req(ar, skb); 22978a6618b0SBartosz Markowski break; 22988a6618b0SBartosz Markowski case WMI_10X_VDEV_RESUME_REQ_EVENTID: 22998a6618b0SBartosz Markowski ath10k_wmi_event_vdev_resume_req(ar, skb); 23008a6618b0SBartosz Markowski break; 23018a6618b0SBartosz Markowski case WMI_10X_SERVICE_READY_EVENTID: 23026f97d256SBartosz Markowski ath10k_wmi_10x_service_ready_event_rx(ar, skb); 23038a6618b0SBartosz Markowski break; 23048a6618b0SBartosz Markowski case WMI_10X_READY_EVENTID: 23058a6618b0SBartosz Markowski ath10k_wmi_ready_event_rx(ar, skb); 23068a6618b0SBartosz Markowski break; 23078a6618b0SBartosz Markowski default: 23088a6618b0SBartosz Markowski ath10k_warn("Unknown eventid: %d\n", id); 23098a6618b0SBartosz Markowski break; 23108a6618b0SBartosz Markowski } 23118a6618b0SBartosz Markowski 23128a6618b0SBartosz Markowski dev_kfree_skb(skb); 23138a6618b0SBartosz Markowski } 23148a6618b0SBartosz Markowski 23158a6618b0SBartosz Markowski 2316ce42870eSBartosz Markowski static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb) 2317ce42870eSBartosz Markowski { 2318ce42870eSBartosz Markowski if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) 23198a6618b0SBartosz Markowski ath10k_wmi_10x_process_rx(ar, skb); 2320ce42870eSBartosz Markowski else 2321ce42870eSBartosz Markowski ath10k_wmi_main_process_rx(ar, skb); 2322ce42870eSBartosz Markowski } 2323ce42870eSBartosz Markowski 23245e3dd157SKalle Valo /* WMI Initialization functions */ 23255e3dd157SKalle Valo int ath10k_wmi_attach(struct ath10k *ar) 23265e3dd157SKalle Valo { 2327ce42870eSBartosz Markowski if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { 2328b7e3adf9SBartosz Markowski ar->wmi.cmd = &wmi_10x_cmd_map; 23296d1506e7SBartosz Markowski ar->wmi.vdev_param = &wmi_10x_vdev_param_map; 2330226a339bSBartosz Markowski ar->wmi.pdev_param = &wmi_10x_pdev_param_map; 2331ce42870eSBartosz Markowski } else { 2332ce42870eSBartosz Markowski ar->wmi.cmd = &wmi_cmd_map; 23336d1506e7SBartosz Markowski ar->wmi.vdev_param = &wmi_vdev_param_map; 2334226a339bSBartosz Markowski ar->wmi.pdev_param = &wmi_pdev_param_map; 2335ce42870eSBartosz Markowski } 2336ce42870eSBartosz Markowski 23375e3dd157SKalle Valo init_completion(&ar->wmi.service_ready); 23385e3dd157SKalle Valo init_completion(&ar->wmi.unified_ready); 2339be8b3943SMichal Kazior init_waitqueue_head(&ar->wmi.tx_credits_wq); 23405e3dd157SKalle Valo 23415e3dd157SKalle Valo return 0; 23425e3dd157SKalle Valo } 23435e3dd157SKalle Valo 23445e3dd157SKalle Valo void ath10k_wmi_detach(struct ath10k *ar) 23455e3dd157SKalle Valo { 2346b3effe61SBartosz Markowski int i; 2347b3effe61SBartosz Markowski 2348b3effe61SBartosz Markowski /* free the host memory chunks requested by firmware */ 2349b3effe61SBartosz Markowski for (i = 0; i < ar->wmi.num_mem_chunks; i++) { 2350b3effe61SBartosz Markowski dma_free_coherent(ar->dev, 2351b3effe61SBartosz Markowski ar->wmi.mem_chunks[i].len, 2352b3effe61SBartosz Markowski ar->wmi.mem_chunks[i].vaddr, 2353b3effe61SBartosz Markowski ar->wmi.mem_chunks[i].paddr); 2354b3effe61SBartosz Markowski } 2355b3effe61SBartosz Markowski 2356b3effe61SBartosz Markowski ar->wmi.num_mem_chunks = 0; 23575e3dd157SKalle Valo } 23585e3dd157SKalle Valo 23595e3dd157SKalle Valo int ath10k_wmi_connect_htc_service(struct ath10k *ar) 23605e3dd157SKalle Valo { 23615e3dd157SKalle Valo int status; 23625e3dd157SKalle Valo struct ath10k_htc_svc_conn_req conn_req; 23635e3dd157SKalle Valo struct ath10k_htc_svc_conn_resp conn_resp; 23645e3dd157SKalle Valo 23655e3dd157SKalle Valo memset(&conn_req, 0, sizeof(conn_req)); 23665e3dd157SKalle Valo memset(&conn_resp, 0, sizeof(conn_resp)); 23675e3dd157SKalle Valo 23685e3dd157SKalle Valo /* these fields are the same for all service endpoints */ 23695e3dd157SKalle Valo conn_req.ep_ops.ep_tx_complete = ath10k_wmi_htc_tx_complete; 23705e3dd157SKalle Valo conn_req.ep_ops.ep_rx_complete = ath10k_wmi_process_rx; 2371be8b3943SMichal Kazior conn_req.ep_ops.ep_tx_credits = ath10k_wmi_op_ep_tx_credits; 23725e3dd157SKalle Valo 23735e3dd157SKalle Valo /* connect to control service */ 23745e3dd157SKalle Valo conn_req.service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL; 23755e3dd157SKalle Valo 2376cd003fadSMichal Kazior status = ath10k_htc_connect_service(&ar->htc, &conn_req, &conn_resp); 23775e3dd157SKalle Valo if (status) { 23785e3dd157SKalle Valo ath10k_warn("failed to connect to WMI CONTROL service status: %d\n", 23795e3dd157SKalle Valo status); 23805e3dd157SKalle Valo return status; 23815e3dd157SKalle Valo } 23825e3dd157SKalle Valo 23835e3dd157SKalle Valo ar->wmi.eid = conn_resp.eid; 23845e3dd157SKalle Valo return 0; 23855e3dd157SKalle Valo } 23865e3dd157SKalle Valo 23875e3dd157SKalle Valo int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, 23885e3dd157SKalle Valo u16 rd5g, u16 ctl2g, u16 ctl5g) 23895e3dd157SKalle Valo { 23905e3dd157SKalle Valo struct wmi_pdev_set_regdomain_cmd *cmd; 23915e3dd157SKalle Valo struct sk_buff *skb; 23925e3dd157SKalle Valo 23935e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 23945e3dd157SKalle Valo if (!skb) 23955e3dd157SKalle Valo return -ENOMEM; 23965e3dd157SKalle Valo 23975e3dd157SKalle Valo cmd = (struct wmi_pdev_set_regdomain_cmd *)skb->data; 23985e3dd157SKalle Valo cmd->reg_domain = __cpu_to_le32(rd); 23995e3dd157SKalle Valo cmd->reg_domain_2G = __cpu_to_le32(rd2g); 24005e3dd157SKalle Valo cmd->reg_domain_5G = __cpu_to_le32(rd5g); 24015e3dd157SKalle Valo cmd->conformance_test_limit_2G = __cpu_to_le32(ctl2g); 24025e3dd157SKalle Valo cmd->conformance_test_limit_5G = __cpu_to_le32(ctl5g); 24035e3dd157SKalle Valo 24045e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 24055e3dd157SKalle Valo "wmi pdev regdomain rd %x rd2g %x rd5g %x ctl2g %x ctl5g %x\n", 24065e3dd157SKalle Valo rd, rd2g, rd5g, ctl2g, ctl5g); 24075e3dd157SKalle Valo 2408ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, 2409ce42870eSBartosz Markowski ar->wmi.cmd->pdev_set_regdomain_cmdid); 24105e3dd157SKalle Valo } 24115e3dd157SKalle Valo 24125e3dd157SKalle Valo int ath10k_wmi_pdev_set_channel(struct ath10k *ar, 24135e3dd157SKalle Valo const struct wmi_channel_arg *arg) 24145e3dd157SKalle Valo { 24155e3dd157SKalle Valo struct wmi_set_channel_cmd *cmd; 24165e3dd157SKalle Valo struct sk_buff *skb; 2417e8a50f8bSMarek Puzyniak u32 ch_flags = 0; 24185e3dd157SKalle Valo 24195e3dd157SKalle Valo if (arg->passive) 24205e3dd157SKalle Valo return -EINVAL; 24215e3dd157SKalle Valo 24225e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 24235e3dd157SKalle Valo if (!skb) 24245e3dd157SKalle Valo return -ENOMEM; 24255e3dd157SKalle Valo 2426e8a50f8bSMarek Puzyniak if (arg->chan_radar) 2427e8a50f8bSMarek Puzyniak ch_flags |= WMI_CHAN_FLAG_DFS; 2428e8a50f8bSMarek Puzyniak 24295e3dd157SKalle Valo cmd = (struct wmi_set_channel_cmd *)skb->data; 24305e3dd157SKalle Valo cmd->chan.mhz = __cpu_to_le32(arg->freq); 24315e3dd157SKalle Valo cmd->chan.band_center_freq1 = __cpu_to_le32(arg->freq); 24325e3dd157SKalle Valo cmd->chan.mode = arg->mode; 2433e8a50f8bSMarek Puzyniak cmd->chan.flags |= __cpu_to_le32(ch_flags); 24345e3dd157SKalle Valo cmd->chan.min_power = arg->min_power; 24355e3dd157SKalle Valo cmd->chan.max_power = arg->max_power; 24365e3dd157SKalle Valo cmd->chan.reg_power = arg->max_reg_power; 24375e3dd157SKalle Valo cmd->chan.reg_classid = arg->reg_class_id; 24385e3dd157SKalle Valo cmd->chan.antenna_max = arg->max_antenna_gain; 24395e3dd157SKalle Valo 24405e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 24415e3dd157SKalle Valo "wmi set channel mode %d freq %d\n", 24425e3dd157SKalle Valo arg->mode, arg->freq); 24435e3dd157SKalle Valo 2444ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, 2445ce42870eSBartosz Markowski ar->wmi.cmd->pdev_set_channel_cmdid); 24465e3dd157SKalle Valo } 24475e3dd157SKalle Valo 24485e3dd157SKalle Valo int ath10k_wmi_pdev_suspend_target(struct ath10k *ar) 24495e3dd157SKalle Valo { 24505e3dd157SKalle Valo struct wmi_pdev_suspend_cmd *cmd; 24515e3dd157SKalle Valo struct sk_buff *skb; 24525e3dd157SKalle Valo 24535e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 24545e3dd157SKalle Valo if (!skb) 24555e3dd157SKalle Valo return -ENOMEM; 24565e3dd157SKalle Valo 24575e3dd157SKalle Valo cmd = (struct wmi_pdev_suspend_cmd *)skb->data; 24585e3dd157SKalle Valo cmd->suspend_opt = WMI_PDEV_SUSPEND; 24595e3dd157SKalle Valo 2460ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_suspend_cmdid); 24615e3dd157SKalle Valo } 24625e3dd157SKalle Valo 24635e3dd157SKalle Valo int ath10k_wmi_pdev_resume_target(struct ath10k *ar) 24645e3dd157SKalle Valo { 24655e3dd157SKalle Valo struct sk_buff *skb; 24665e3dd157SKalle Valo 24675e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(0); 24685e3dd157SKalle Valo if (skb == NULL) 24695e3dd157SKalle Valo return -ENOMEM; 24705e3dd157SKalle Valo 2471ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_resume_cmdid); 24725e3dd157SKalle Valo } 24735e3dd157SKalle Valo 2474226a339bSBartosz Markowski int ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value) 24755e3dd157SKalle Valo { 24765e3dd157SKalle Valo struct wmi_pdev_set_param_cmd *cmd; 24775e3dd157SKalle Valo struct sk_buff *skb; 24785e3dd157SKalle Valo 2479226a339bSBartosz Markowski if (id == WMI_PDEV_PARAM_UNSUPPORTED) { 2480226a339bSBartosz Markowski ath10k_warn("pdev param %d not supported by firmware\n", id); 2481d544943aSBartosz Markowski return -EOPNOTSUPP; 2482226a339bSBartosz Markowski } 2483226a339bSBartosz Markowski 24845e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 24855e3dd157SKalle Valo if (!skb) 24865e3dd157SKalle Valo return -ENOMEM; 24875e3dd157SKalle Valo 24885e3dd157SKalle Valo cmd = (struct wmi_pdev_set_param_cmd *)skb->data; 24895e3dd157SKalle Valo cmd->param_id = __cpu_to_le32(id); 24905e3dd157SKalle Valo cmd->param_value = __cpu_to_le32(value); 24915e3dd157SKalle Valo 24925e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set param %d value %d\n", 24935e3dd157SKalle Valo id, value); 2494ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid); 24955e3dd157SKalle Valo } 24965e3dd157SKalle Valo 249712b2b9e3SBartosz Markowski static int ath10k_wmi_main_cmd_init(struct ath10k *ar) 24985e3dd157SKalle Valo { 24995e3dd157SKalle Valo struct wmi_init_cmd *cmd; 25005e3dd157SKalle Valo struct sk_buff *buf; 25015e3dd157SKalle Valo struct wmi_resource_config config = {}; 2502b3effe61SBartosz Markowski u32 len, val; 2503b3effe61SBartosz Markowski int i; 25045e3dd157SKalle Valo 25055e3dd157SKalle Valo config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS); 25065e3dd157SKalle Valo config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS); 25075e3dd157SKalle Valo config.num_offload_peers = __cpu_to_le32(TARGET_NUM_OFFLOAD_PEERS); 25085e3dd157SKalle Valo 25095e3dd157SKalle Valo config.num_offload_reorder_bufs = 25105e3dd157SKalle Valo __cpu_to_le32(TARGET_NUM_OFFLOAD_REORDER_BUFS); 25115e3dd157SKalle Valo 25125e3dd157SKalle Valo config.num_peer_keys = __cpu_to_le32(TARGET_NUM_PEER_KEYS); 25135e3dd157SKalle Valo config.num_tids = __cpu_to_le32(TARGET_NUM_TIDS); 25145e3dd157SKalle Valo config.ast_skid_limit = __cpu_to_le32(TARGET_AST_SKID_LIMIT); 25155e3dd157SKalle Valo config.tx_chain_mask = __cpu_to_le32(TARGET_TX_CHAIN_MASK); 25165e3dd157SKalle Valo config.rx_chain_mask = __cpu_to_le32(TARGET_RX_CHAIN_MASK); 25175e3dd157SKalle Valo config.rx_timeout_pri_vo = __cpu_to_le32(TARGET_RX_TIMEOUT_LO_PRI); 25185e3dd157SKalle Valo config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_RX_TIMEOUT_LO_PRI); 25195e3dd157SKalle Valo config.rx_timeout_pri_be = __cpu_to_le32(TARGET_RX_TIMEOUT_LO_PRI); 25205e3dd157SKalle Valo config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_RX_TIMEOUT_HI_PRI); 25215e3dd157SKalle Valo config.rx_decap_mode = __cpu_to_le32(TARGET_RX_DECAP_MODE); 25225e3dd157SKalle Valo 25235e3dd157SKalle Valo config.scan_max_pending_reqs = 25245e3dd157SKalle Valo __cpu_to_le32(TARGET_SCAN_MAX_PENDING_REQS); 25255e3dd157SKalle Valo 25265e3dd157SKalle Valo config.bmiss_offload_max_vdev = 25275e3dd157SKalle Valo __cpu_to_le32(TARGET_BMISS_OFFLOAD_MAX_VDEV); 25285e3dd157SKalle Valo 25295e3dd157SKalle Valo config.roam_offload_max_vdev = 25305e3dd157SKalle Valo __cpu_to_le32(TARGET_ROAM_OFFLOAD_MAX_VDEV); 25315e3dd157SKalle Valo 25325e3dd157SKalle Valo config.roam_offload_max_ap_profiles = 25335e3dd157SKalle Valo __cpu_to_le32(TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES); 25345e3dd157SKalle Valo 25355e3dd157SKalle Valo config.num_mcast_groups = __cpu_to_le32(TARGET_NUM_MCAST_GROUPS); 25365e3dd157SKalle Valo config.num_mcast_table_elems = 25375e3dd157SKalle Valo __cpu_to_le32(TARGET_NUM_MCAST_TABLE_ELEMS); 25385e3dd157SKalle Valo 25395e3dd157SKalle Valo config.mcast2ucast_mode = __cpu_to_le32(TARGET_MCAST2UCAST_MODE); 25405e3dd157SKalle Valo config.tx_dbg_log_size = __cpu_to_le32(TARGET_TX_DBG_LOG_SIZE); 25415e3dd157SKalle Valo config.num_wds_entries = __cpu_to_le32(TARGET_NUM_WDS_ENTRIES); 25425e3dd157SKalle Valo config.dma_burst_size = __cpu_to_le32(TARGET_DMA_BURST_SIZE); 25435e3dd157SKalle Valo config.mac_aggr_delim = __cpu_to_le32(TARGET_MAC_AGGR_DELIM); 25445e3dd157SKalle Valo 25455e3dd157SKalle Valo val = TARGET_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK; 25465e3dd157SKalle Valo config.rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(val); 25475e3dd157SKalle Valo 25485e3dd157SKalle Valo config.vow_config = __cpu_to_le32(TARGET_VOW_CONFIG); 25495e3dd157SKalle Valo 25505e3dd157SKalle Valo config.gtk_offload_max_vdev = 25515e3dd157SKalle Valo __cpu_to_le32(TARGET_GTK_OFFLOAD_MAX_VDEV); 25525e3dd157SKalle Valo 25535e3dd157SKalle Valo config.num_msdu_desc = __cpu_to_le32(TARGET_NUM_MSDU_DESC); 25545e3dd157SKalle Valo config.max_frag_entries = __cpu_to_le32(TARGET_MAX_FRAG_ENTRIES); 25555e3dd157SKalle Valo 2556b3effe61SBartosz Markowski len = sizeof(*cmd) + 2557b3effe61SBartosz Markowski (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks); 2558b3effe61SBartosz Markowski 2559b3effe61SBartosz Markowski buf = ath10k_wmi_alloc_skb(len); 25605e3dd157SKalle Valo if (!buf) 25615e3dd157SKalle Valo return -ENOMEM; 25625e3dd157SKalle Valo 25635e3dd157SKalle Valo cmd = (struct wmi_init_cmd *)buf->data; 2564b3effe61SBartosz Markowski 2565b3effe61SBartosz Markowski if (ar->wmi.num_mem_chunks == 0) { 25665e3dd157SKalle Valo cmd->num_host_mem_chunks = 0; 2567b3effe61SBartosz Markowski goto out; 2568b3effe61SBartosz Markowski } 2569b3effe61SBartosz Markowski 2570b3effe61SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", 25715c54a7bfSMichal Kazior ar->wmi.num_mem_chunks); 2572b3effe61SBartosz Markowski 2573b3effe61SBartosz Markowski cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); 2574b3effe61SBartosz Markowski 2575b3effe61SBartosz Markowski for (i = 0; i < ar->wmi.num_mem_chunks; i++) { 2576b3effe61SBartosz Markowski cmd->host_mem_chunks[i].ptr = 2577b3effe61SBartosz Markowski __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); 2578b3effe61SBartosz Markowski cmd->host_mem_chunks[i].size = 2579b3effe61SBartosz Markowski __cpu_to_le32(ar->wmi.mem_chunks[i].len); 2580b3effe61SBartosz Markowski cmd->host_mem_chunks[i].req_id = 2581b3effe61SBartosz Markowski __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); 2582b3effe61SBartosz Markowski 2583b3effe61SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, 25845c54a7bfSMichal Kazior "wmi chunk %d len %d requested, addr 0x%llx\n", 2585b3effe61SBartosz Markowski i, 25865c54a7bfSMichal Kazior ar->wmi.mem_chunks[i].len, 25875c54a7bfSMichal Kazior (unsigned long long)ar->wmi.mem_chunks[i].paddr); 2588b3effe61SBartosz Markowski } 2589b3effe61SBartosz Markowski out: 25905e3dd157SKalle Valo memcpy(&cmd->resource_config, &config, sizeof(config)); 25915e3dd157SKalle Valo 25925e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi init\n"); 2593ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); 25945e3dd157SKalle Valo } 25955e3dd157SKalle Valo 259612b2b9e3SBartosz Markowski static int ath10k_wmi_10x_cmd_init(struct ath10k *ar) 259712b2b9e3SBartosz Markowski { 259812b2b9e3SBartosz Markowski struct wmi_init_cmd_10x *cmd; 259912b2b9e3SBartosz Markowski struct sk_buff *buf; 260012b2b9e3SBartosz Markowski struct wmi_resource_config_10x config = {}; 260112b2b9e3SBartosz Markowski u32 len, val; 260212b2b9e3SBartosz Markowski int i; 260312b2b9e3SBartosz Markowski 2604ec6a73f0SBartosz Markowski config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); 2605ec6a73f0SBartosz Markowski config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); 2606ec6a73f0SBartosz Markowski config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS); 2607ec6a73f0SBartosz Markowski config.num_tids = __cpu_to_le32(TARGET_10X_NUM_TIDS); 2608ec6a73f0SBartosz Markowski config.ast_skid_limit = __cpu_to_le32(TARGET_10X_AST_SKID_LIMIT); 2609ec6a73f0SBartosz Markowski config.tx_chain_mask = __cpu_to_le32(TARGET_10X_TX_CHAIN_MASK); 2610ec6a73f0SBartosz Markowski config.rx_chain_mask = __cpu_to_le32(TARGET_10X_RX_CHAIN_MASK); 2611ec6a73f0SBartosz Markowski config.rx_timeout_pri_vo = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI); 2612ec6a73f0SBartosz Markowski config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI); 2613ec6a73f0SBartosz Markowski config.rx_timeout_pri_be = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI); 2614ec6a73f0SBartosz Markowski config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_HI_PRI); 2615ec6a73f0SBartosz Markowski config.rx_decap_mode = __cpu_to_le32(TARGET_10X_RX_DECAP_MODE); 261612b2b9e3SBartosz Markowski 261712b2b9e3SBartosz Markowski config.scan_max_pending_reqs = 2618ec6a73f0SBartosz Markowski __cpu_to_le32(TARGET_10X_SCAN_MAX_PENDING_REQS); 261912b2b9e3SBartosz Markowski 262012b2b9e3SBartosz Markowski config.bmiss_offload_max_vdev = 2621ec6a73f0SBartosz Markowski __cpu_to_le32(TARGET_10X_BMISS_OFFLOAD_MAX_VDEV); 262212b2b9e3SBartosz Markowski 262312b2b9e3SBartosz Markowski config.roam_offload_max_vdev = 2624ec6a73f0SBartosz Markowski __cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_VDEV); 262512b2b9e3SBartosz Markowski 262612b2b9e3SBartosz Markowski config.roam_offload_max_ap_profiles = 2627ec6a73f0SBartosz Markowski __cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_AP_PROFILES); 262812b2b9e3SBartosz Markowski 2629ec6a73f0SBartosz Markowski config.num_mcast_groups = __cpu_to_le32(TARGET_10X_NUM_MCAST_GROUPS); 263012b2b9e3SBartosz Markowski config.num_mcast_table_elems = 2631ec6a73f0SBartosz Markowski __cpu_to_le32(TARGET_10X_NUM_MCAST_TABLE_ELEMS); 263212b2b9e3SBartosz Markowski 2633ec6a73f0SBartosz Markowski config.mcast2ucast_mode = __cpu_to_le32(TARGET_10X_MCAST2UCAST_MODE); 2634ec6a73f0SBartosz Markowski config.tx_dbg_log_size = __cpu_to_le32(TARGET_10X_TX_DBG_LOG_SIZE); 2635ec6a73f0SBartosz Markowski config.num_wds_entries = __cpu_to_le32(TARGET_10X_NUM_WDS_ENTRIES); 2636ec6a73f0SBartosz Markowski config.dma_burst_size = __cpu_to_le32(TARGET_10X_DMA_BURST_SIZE); 2637ec6a73f0SBartosz Markowski config.mac_aggr_delim = __cpu_to_le32(TARGET_10X_MAC_AGGR_DELIM); 263812b2b9e3SBartosz Markowski 2639ec6a73f0SBartosz Markowski val = TARGET_10X_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK; 264012b2b9e3SBartosz Markowski config.rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(val); 264112b2b9e3SBartosz Markowski 2642ec6a73f0SBartosz Markowski config.vow_config = __cpu_to_le32(TARGET_10X_VOW_CONFIG); 264312b2b9e3SBartosz Markowski 2644ec6a73f0SBartosz Markowski config.num_msdu_desc = __cpu_to_le32(TARGET_10X_NUM_MSDU_DESC); 2645ec6a73f0SBartosz Markowski config.max_frag_entries = __cpu_to_le32(TARGET_10X_MAX_FRAG_ENTRIES); 264612b2b9e3SBartosz Markowski 264712b2b9e3SBartosz Markowski len = sizeof(*cmd) + 264812b2b9e3SBartosz Markowski (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks); 264912b2b9e3SBartosz Markowski 265012b2b9e3SBartosz Markowski buf = ath10k_wmi_alloc_skb(len); 265112b2b9e3SBartosz Markowski if (!buf) 265212b2b9e3SBartosz Markowski return -ENOMEM; 265312b2b9e3SBartosz Markowski 265412b2b9e3SBartosz Markowski cmd = (struct wmi_init_cmd_10x *)buf->data; 265512b2b9e3SBartosz Markowski 265612b2b9e3SBartosz Markowski if (ar->wmi.num_mem_chunks == 0) { 265712b2b9e3SBartosz Markowski cmd->num_host_mem_chunks = 0; 265812b2b9e3SBartosz Markowski goto out; 265912b2b9e3SBartosz Markowski } 266012b2b9e3SBartosz Markowski 266112b2b9e3SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", 26625c54a7bfSMichal Kazior ar->wmi.num_mem_chunks); 266312b2b9e3SBartosz Markowski 266412b2b9e3SBartosz Markowski cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); 266512b2b9e3SBartosz Markowski 266612b2b9e3SBartosz Markowski for (i = 0; i < ar->wmi.num_mem_chunks; i++) { 266712b2b9e3SBartosz Markowski cmd->host_mem_chunks[i].ptr = 266812b2b9e3SBartosz Markowski __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); 266912b2b9e3SBartosz Markowski cmd->host_mem_chunks[i].size = 267012b2b9e3SBartosz Markowski __cpu_to_le32(ar->wmi.mem_chunks[i].len); 267112b2b9e3SBartosz Markowski cmd->host_mem_chunks[i].req_id = 267212b2b9e3SBartosz Markowski __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); 267312b2b9e3SBartosz Markowski 267412b2b9e3SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, 26755c54a7bfSMichal Kazior "wmi chunk %d len %d requested, addr 0x%llx\n", 267612b2b9e3SBartosz Markowski i, 26775c54a7bfSMichal Kazior ar->wmi.mem_chunks[i].len, 26785c54a7bfSMichal Kazior (unsigned long long)ar->wmi.mem_chunks[i].paddr); 267912b2b9e3SBartosz Markowski } 268012b2b9e3SBartosz Markowski out: 268112b2b9e3SBartosz Markowski memcpy(&cmd->resource_config, &config, sizeof(config)); 268212b2b9e3SBartosz Markowski 268312b2b9e3SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "wmi init 10x\n"); 268412b2b9e3SBartosz Markowski return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); 268512b2b9e3SBartosz Markowski } 268612b2b9e3SBartosz Markowski 268712b2b9e3SBartosz Markowski int ath10k_wmi_cmd_init(struct ath10k *ar) 268812b2b9e3SBartosz Markowski { 268912b2b9e3SBartosz Markowski int ret; 269012b2b9e3SBartosz Markowski 269112b2b9e3SBartosz Markowski if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) 269212b2b9e3SBartosz Markowski ret = ath10k_wmi_10x_cmd_init(ar); 269312b2b9e3SBartosz Markowski else 269412b2b9e3SBartosz Markowski ret = ath10k_wmi_main_cmd_init(ar); 269512b2b9e3SBartosz Markowski 269612b2b9e3SBartosz Markowski return ret; 269712b2b9e3SBartosz Markowski } 269812b2b9e3SBartosz Markowski 269989b7e766SBartosz Markowski static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar, 270089b7e766SBartosz Markowski const struct wmi_start_scan_arg *arg) 27015e3dd157SKalle Valo { 27025e3dd157SKalle Valo int len; 27035e3dd157SKalle Valo 270489b7e766SBartosz Markowski if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) 270589b7e766SBartosz Markowski len = sizeof(struct wmi_start_scan_cmd_10x); 270689b7e766SBartosz Markowski else 27075e3dd157SKalle Valo len = sizeof(struct wmi_start_scan_cmd); 27085e3dd157SKalle Valo 27095e3dd157SKalle Valo if (arg->ie_len) { 27105e3dd157SKalle Valo if (!arg->ie) 27115e3dd157SKalle Valo return -EINVAL; 27125e3dd157SKalle Valo if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN) 27135e3dd157SKalle Valo return -EINVAL; 27145e3dd157SKalle Valo 27155e3dd157SKalle Valo len += sizeof(struct wmi_ie_data); 27165e3dd157SKalle Valo len += roundup(arg->ie_len, 4); 27175e3dd157SKalle Valo } 27185e3dd157SKalle Valo 27195e3dd157SKalle Valo if (arg->n_channels) { 27205e3dd157SKalle Valo if (!arg->channels) 27215e3dd157SKalle Valo return -EINVAL; 27225e3dd157SKalle Valo if (arg->n_channels > ARRAY_SIZE(arg->channels)) 27235e3dd157SKalle Valo return -EINVAL; 27245e3dd157SKalle Valo 27255e3dd157SKalle Valo len += sizeof(struct wmi_chan_list); 27265e3dd157SKalle Valo len += sizeof(__le32) * arg->n_channels; 27275e3dd157SKalle Valo } 27285e3dd157SKalle Valo 27295e3dd157SKalle Valo if (arg->n_ssids) { 27305e3dd157SKalle Valo if (!arg->ssids) 27315e3dd157SKalle Valo return -EINVAL; 27325e3dd157SKalle Valo if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID) 27335e3dd157SKalle Valo return -EINVAL; 27345e3dd157SKalle Valo 27355e3dd157SKalle Valo len += sizeof(struct wmi_ssid_list); 27365e3dd157SKalle Valo len += sizeof(struct wmi_ssid) * arg->n_ssids; 27375e3dd157SKalle Valo } 27385e3dd157SKalle Valo 27395e3dd157SKalle Valo if (arg->n_bssids) { 27405e3dd157SKalle Valo if (!arg->bssids) 27415e3dd157SKalle Valo return -EINVAL; 27425e3dd157SKalle Valo if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID) 27435e3dd157SKalle Valo return -EINVAL; 27445e3dd157SKalle Valo 27455e3dd157SKalle Valo len += sizeof(struct wmi_bssid_list); 27465e3dd157SKalle Valo len += sizeof(struct wmi_mac_addr) * arg->n_bssids; 27475e3dd157SKalle Valo } 27485e3dd157SKalle Valo 27495e3dd157SKalle Valo return len; 27505e3dd157SKalle Valo } 27515e3dd157SKalle Valo 27525e3dd157SKalle Valo int ath10k_wmi_start_scan(struct ath10k *ar, 27535e3dd157SKalle Valo const struct wmi_start_scan_arg *arg) 27545e3dd157SKalle Valo { 27555e3dd157SKalle Valo struct wmi_start_scan_cmd *cmd; 27565e3dd157SKalle Valo struct sk_buff *skb; 27575e3dd157SKalle Valo struct wmi_ie_data *ie; 27585e3dd157SKalle Valo struct wmi_chan_list *channels; 27595e3dd157SKalle Valo struct wmi_ssid_list *ssids; 27605e3dd157SKalle Valo struct wmi_bssid_list *bssids; 27615e3dd157SKalle Valo u32 scan_id; 27625e3dd157SKalle Valo u32 scan_req_id; 27635e3dd157SKalle Valo int off; 27645e3dd157SKalle Valo int len = 0; 27655e3dd157SKalle Valo int i; 27665e3dd157SKalle Valo 276789b7e766SBartosz Markowski len = ath10k_wmi_start_scan_calc_len(ar, arg); 27685e3dd157SKalle Valo if (len < 0) 27695e3dd157SKalle Valo return len; /* len contains error code here */ 27705e3dd157SKalle Valo 27715e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(len); 27725e3dd157SKalle Valo if (!skb) 27735e3dd157SKalle Valo return -ENOMEM; 27745e3dd157SKalle Valo 27755e3dd157SKalle Valo scan_id = WMI_HOST_SCAN_REQ_ID_PREFIX; 27765e3dd157SKalle Valo scan_id |= arg->scan_id; 27775e3dd157SKalle Valo 27785e3dd157SKalle Valo scan_req_id = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX; 27795e3dd157SKalle Valo scan_req_id |= arg->scan_req_id; 27805e3dd157SKalle Valo 27815e3dd157SKalle Valo cmd = (struct wmi_start_scan_cmd *)skb->data; 27825e3dd157SKalle Valo cmd->scan_id = __cpu_to_le32(scan_id); 27835e3dd157SKalle Valo cmd->scan_req_id = __cpu_to_le32(scan_req_id); 27845e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(arg->vdev_id); 27855e3dd157SKalle Valo cmd->scan_priority = __cpu_to_le32(arg->scan_priority); 27865e3dd157SKalle Valo cmd->notify_scan_events = __cpu_to_le32(arg->notify_scan_events); 27875e3dd157SKalle Valo cmd->dwell_time_active = __cpu_to_le32(arg->dwell_time_active); 27885e3dd157SKalle Valo cmd->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive); 27895e3dd157SKalle Valo cmd->min_rest_time = __cpu_to_le32(arg->min_rest_time); 27905e3dd157SKalle Valo cmd->max_rest_time = __cpu_to_le32(arg->max_rest_time); 27915e3dd157SKalle Valo cmd->repeat_probe_time = __cpu_to_le32(arg->repeat_probe_time); 27925e3dd157SKalle Valo cmd->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time); 27935e3dd157SKalle Valo cmd->idle_time = __cpu_to_le32(arg->idle_time); 27945e3dd157SKalle Valo cmd->max_scan_time = __cpu_to_le32(arg->max_scan_time); 27955e3dd157SKalle Valo cmd->probe_delay = __cpu_to_le32(arg->probe_delay); 27965e3dd157SKalle Valo cmd->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags); 27975e3dd157SKalle Valo 27985e3dd157SKalle Valo /* TLV list starts after fields included in the struct */ 279989b7e766SBartosz Markowski /* There's just one filed that differes the two start_scan 280089b7e766SBartosz Markowski * structures - burst_duration, which we are not using btw, 280189b7e766SBartosz Markowski no point to make the split here, just shift the buffer to fit with 280289b7e766SBartosz Markowski given FW */ 280389b7e766SBartosz Markowski if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) 280489b7e766SBartosz Markowski off = sizeof(struct wmi_start_scan_cmd_10x); 280589b7e766SBartosz Markowski else 280689b7e766SBartosz Markowski off = sizeof(struct wmi_start_scan_cmd); 28075e3dd157SKalle Valo 28085e3dd157SKalle Valo if (arg->n_channels) { 28095e3dd157SKalle Valo channels = (void *)skb->data + off; 28105e3dd157SKalle Valo channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG); 28115e3dd157SKalle Valo channels->num_chan = __cpu_to_le32(arg->n_channels); 28125e3dd157SKalle Valo 28135e3dd157SKalle Valo for (i = 0; i < arg->n_channels; i++) 28145e3dd157SKalle Valo channels->channel_list[i] = 28155e3dd157SKalle Valo __cpu_to_le32(arg->channels[i]); 28165e3dd157SKalle Valo 28175e3dd157SKalle Valo off += sizeof(*channels); 28185e3dd157SKalle Valo off += sizeof(__le32) * arg->n_channels; 28195e3dd157SKalle Valo } 28205e3dd157SKalle Valo 28215e3dd157SKalle Valo if (arg->n_ssids) { 28225e3dd157SKalle Valo ssids = (void *)skb->data + off; 28235e3dd157SKalle Valo ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG); 28245e3dd157SKalle Valo ssids->num_ssids = __cpu_to_le32(arg->n_ssids); 28255e3dd157SKalle Valo 28265e3dd157SKalle Valo for (i = 0; i < arg->n_ssids; i++) { 28275e3dd157SKalle Valo ssids->ssids[i].ssid_len = 28285e3dd157SKalle Valo __cpu_to_le32(arg->ssids[i].len); 28295e3dd157SKalle Valo memcpy(&ssids->ssids[i].ssid, 28305e3dd157SKalle Valo arg->ssids[i].ssid, 28315e3dd157SKalle Valo arg->ssids[i].len); 28325e3dd157SKalle Valo } 28335e3dd157SKalle Valo 28345e3dd157SKalle Valo off += sizeof(*ssids); 28355e3dd157SKalle Valo off += sizeof(struct wmi_ssid) * arg->n_ssids; 28365e3dd157SKalle Valo } 28375e3dd157SKalle Valo 28385e3dd157SKalle Valo if (arg->n_bssids) { 28395e3dd157SKalle Valo bssids = (void *)skb->data + off; 28405e3dd157SKalle Valo bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG); 28415e3dd157SKalle Valo bssids->num_bssid = __cpu_to_le32(arg->n_bssids); 28425e3dd157SKalle Valo 28435e3dd157SKalle Valo for (i = 0; i < arg->n_bssids; i++) 28445e3dd157SKalle Valo memcpy(&bssids->bssid_list[i], 28455e3dd157SKalle Valo arg->bssids[i].bssid, 28465e3dd157SKalle Valo ETH_ALEN); 28475e3dd157SKalle Valo 28485e3dd157SKalle Valo off += sizeof(*bssids); 28495e3dd157SKalle Valo off += sizeof(struct wmi_mac_addr) * arg->n_bssids; 28505e3dd157SKalle Valo } 28515e3dd157SKalle Valo 28525e3dd157SKalle Valo if (arg->ie_len) { 28535e3dd157SKalle Valo ie = (void *)skb->data + off; 28545e3dd157SKalle Valo ie->tag = __cpu_to_le32(WMI_IE_TAG); 28555e3dd157SKalle Valo ie->ie_len = __cpu_to_le32(arg->ie_len); 28565e3dd157SKalle Valo memcpy(ie->ie_data, arg->ie, arg->ie_len); 28575e3dd157SKalle Valo 28585e3dd157SKalle Valo off += sizeof(*ie); 28595e3dd157SKalle Valo off += roundup(arg->ie_len, 4); 28605e3dd157SKalle Valo } 28615e3dd157SKalle Valo 28625e3dd157SKalle Valo if (off != skb->len) { 28635e3dd157SKalle Valo dev_kfree_skb(skb); 28645e3dd157SKalle Valo return -EINVAL; 28655e3dd157SKalle Valo } 28665e3dd157SKalle Valo 28675e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi start scan\n"); 2868ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->start_scan_cmdid); 28695e3dd157SKalle Valo } 28705e3dd157SKalle Valo 28715e3dd157SKalle Valo void ath10k_wmi_start_scan_init(struct ath10k *ar, 28725e3dd157SKalle Valo struct wmi_start_scan_arg *arg) 28735e3dd157SKalle Valo { 28745e3dd157SKalle Valo /* setup commonly used values */ 28755e3dd157SKalle Valo arg->scan_req_id = 1; 28765e3dd157SKalle Valo arg->scan_priority = WMI_SCAN_PRIORITY_LOW; 28775e3dd157SKalle Valo arg->dwell_time_active = 50; 28785e3dd157SKalle Valo arg->dwell_time_passive = 150; 28795e3dd157SKalle Valo arg->min_rest_time = 50; 28805e3dd157SKalle Valo arg->max_rest_time = 500; 28815e3dd157SKalle Valo arg->repeat_probe_time = 0; 28825e3dd157SKalle Valo arg->probe_spacing_time = 0; 28835e3dd157SKalle Valo arg->idle_time = 0; 2884c322892fSBartosz Markowski arg->max_scan_time = 20000; 28855e3dd157SKalle Valo arg->probe_delay = 5; 28865e3dd157SKalle Valo arg->notify_scan_events = WMI_SCAN_EVENT_STARTED 28875e3dd157SKalle Valo | WMI_SCAN_EVENT_COMPLETED 28885e3dd157SKalle Valo | WMI_SCAN_EVENT_BSS_CHANNEL 28895e3dd157SKalle Valo | WMI_SCAN_EVENT_FOREIGN_CHANNEL 28905e3dd157SKalle Valo | WMI_SCAN_EVENT_DEQUEUED; 28915e3dd157SKalle Valo arg->scan_ctrl_flags |= WMI_SCAN_ADD_OFDM_RATES; 28925e3dd157SKalle Valo arg->scan_ctrl_flags |= WMI_SCAN_CHAN_STAT_EVENT; 28935e3dd157SKalle Valo arg->n_bssids = 1; 28945e3dd157SKalle Valo arg->bssids[0].bssid = "\xFF\xFF\xFF\xFF\xFF\xFF"; 28955e3dd157SKalle Valo } 28965e3dd157SKalle Valo 28975e3dd157SKalle Valo int ath10k_wmi_stop_scan(struct ath10k *ar, const struct wmi_stop_scan_arg *arg) 28985e3dd157SKalle Valo { 28995e3dd157SKalle Valo struct wmi_stop_scan_cmd *cmd; 29005e3dd157SKalle Valo struct sk_buff *skb; 29015e3dd157SKalle Valo u32 scan_id; 29025e3dd157SKalle Valo u32 req_id; 29035e3dd157SKalle Valo 29045e3dd157SKalle Valo if (arg->req_id > 0xFFF) 29055e3dd157SKalle Valo return -EINVAL; 29065e3dd157SKalle Valo if (arg->req_type == WMI_SCAN_STOP_ONE && arg->u.scan_id > 0xFFF) 29075e3dd157SKalle Valo return -EINVAL; 29085e3dd157SKalle Valo 29095e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 29105e3dd157SKalle Valo if (!skb) 29115e3dd157SKalle Valo return -ENOMEM; 29125e3dd157SKalle Valo 29135e3dd157SKalle Valo scan_id = arg->u.scan_id; 29145e3dd157SKalle Valo scan_id |= WMI_HOST_SCAN_REQ_ID_PREFIX; 29155e3dd157SKalle Valo 29165e3dd157SKalle Valo req_id = arg->req_id; 29175e3dd157SKalle Valo req_id |= WMI_HOST_SCAN_REQUESTOR_ID_PREFIX; 29185e3dd157SKalle Valo 29195e3dd157SKalle Valo cmd = (struct wmi_stop_scan_cmd *)skb->data; 29205e3dd157SKalle Valo cmd->req_type = __cpu_to_le32(arg->req_type); 29215e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(arg->u.vdev_id); 29225e3dd157SKalle Valo cmd->scan_id = __cpu_to_le32(scan_id); 29235e3dd157SKalle Valo cmd->scan_req_id = __cpu_to_le32(req_id); 29245e3dd157SKalle Valo 29255e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 29265e3dd157SKalle Valo "wmi stop scan reqid %d req_type %d vdev/scan_id %d\n", 29275e3dd157SKalle Valo arg->req_id, arg->req_type, arg->u.scan_id); 2928ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->stop_scan_cmdid); 29295e3dd157SKalle Valo } 29305e3dd157SKalle Valo 29315e3dd157SKalle Valo int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id, 29325e3dd157SKalle Valo enum wmi_vdev_type type, 29335e3dd157SKalle Valo enum wmi_vdev_subtype subtype, 29345e3dd157SKalle Valo const u8 macaddr[ETH_ALEN]) 29355e3dd157SKalle Valo { 29365e3dd157SKalle Valo struct wmi_vdev_create_cmd *cmd; 29375e3dd157SKalle Valo struct sk_buff *skb; 29385e3dd157SKalle Valo 29395e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 29405e3dd157SKalle Valo if (!skb) 29415e3dd157SKalle Valo return -ENOMEM; 29425e3dd157SKalle Valo 29435e3dd157SKalle Valo cmd = (struct wmi_vdev_create_cmd *)skb->data; 29445e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 29455e3dd157SKalle Valo cmd->vdev_type = __cpu_to_le32(type); 29465e3dd157SKalle Valo cmd->vdev_subtype = __cpu_to_le32(subtype); 29475e3dd157SKalle Valo memcpy(cmd->vdev_macaddr.addr, macaddr, ETH_ALEN); 29485e3dd157SKalle Valo 29495e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 29505e3dd157SKalle Valo "WMI vdev create: id %d type %d subtype %d macaddr %pM\n", 29515e3dd157SKalle Valo vdev_id, type, subtype, macaddr); 29525e3dd157SKalle Valo 2953ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_create_cmdid); 29545e3dd157SKalle Valo } 29555e3dd157SKalle Valo 29565e3dd157SKalle Valo int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id) 29575e3dd157SKalle Valo { 29585e3dd157SKalle Valo struct wmi_vdev_delete_cmd *cmd; 29595e3dd157SKalle Valo struct sk_buff *skb; 29605e3dd157SKalle Valo 29615e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 29625e3dd157SKalle Valo if (!skb) 29635e3dd157SKalle Valo return -ENOMEM; 29645e3dd157SKalle Valo 29655e3dd157SKalle Valo cmd = (struct wmi_vdev_delete_cmd *)skb->data; 29665e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 29675e3dd157SKalle Valo 29685e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 29695e3dd157SKalle Valo "WMI vdev delete id %d\n", vdev_id); 29705e3dd157SKalle Valo 2971ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_delete_cmdid); 29725e3dd157SKalle Valo } 29735e3dd157SKalle Valo 29745e3dd157SKalle Valo static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, 29755e3dd157SKalle Valo const struct wmi_vdev_start_request_arg *arg, 2976ce42870eSBartosz Markowski u32 cmd_id) 29775e3dd157SKalle Valo { 29785e3dd157SKalle Valo struct wmi_vdev_start_request_cmd *cmd; 29795e3dd157SKalle Valo struct sk_buff *skb; 29805e3dd157SKalle Valo const char *cmdname; 29815e3dd157SKalle Valo u32 flags = 0; 2982e8a50f8bSMarek Puzyniak u32 ch_flags = 0; 29835e3dd157SKalle Valo 2984ce42870eSBartosz Markowski if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid && 2985ce42870eSBartosz Markowski cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid) 29865e3dd157SKalle Valo return -EINVAL; 29875e3dd157SKalle Valo if (WARN_ON(arg->ssid && arg->ssid_len == 0)) 29885e3dd157SKalle Valo return -EINVAL; 29895e3dd157SKalle Valo if (WARN_ON(arg->hidden_ssid && !arg->ssid)) 29905e3dd157SKalle Valo return -EINVAL; 29915e3dd157SKalle Valo if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid))) 29925e3dd157SKalle Valo return -EINVAL; 29935e3dd157SKalle Valo 2994ce42870eSBartosz Markowski if (cmd_id == ar->wmi.cmd->vdev_start_request_cmdid) 29955e3dd157SKalle Valo cmdname = "start"; 2996ce42870eSBartosz Markowski else if (cmd_id == ar->wmi.cmd->vdev_restart_request_cmdid) 29975e3dd157SKalle Valo cmdname = "restart"; 29985e3dd157SKalle Valo else 29995e3dd157SKalle Valo return -EINVAL; /* should not happen, we already check cmd_id */ 30005e3dd157SKalle Valo 30015e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 30025e3dd157SKalle Valo if (!skb) 30035e3dd157SKalle Valo return -ENOMEM; 30045e3dd157SKalle Valo 30055e3dd157SKalle Valo if (arg->hidden_ssid) 30065e3dd157SKalle Valo flags |= WMI_VDEV_START_HIDDEN_SSID; 30075e3dd157SKalle Valo if (arg->pmf_enabled) 30085e3dd157SKalle Valo flags |= WMI_VDEV_START_PMF_ENABLED; 3009e8a50f8bSMarek Puzyniak if (arg->channel.chan_radar) 3010e8a50f8bSMarek Puzyniak ch_flags |= WMI_CHAN_FLAG_DFS; 30115e3dd157SKalle Valo 30125e3dd157SKalle Valo cmd = (struct wmi_vdev_start_request_cmd *)skb->data; 30135e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(arg->vdev_id); 30145e3dd157SKalle Valo cmd->disable_hw_ack = __cpu_to_le32(arg->disable_hw_ack); 30155e3dd157SKalle Valo cmd->beacon_interval = __cpu_to_le32(arg->bcn_intval); 30165e3dd157SKalle Valo cmd->dtim_period = __cpu_to_le32(arg->dtim_period); 30175e3dd157SKalle Valo cmd->flags = __cpu_to_le32(flags); 30185e3dd157SKalle Valo cmd->bcn_tx_rate = __cpu_to_le32(arg->bcn_tx_rate); 30195e3dd157SKalle Valo cmd->bcn_tx_power = __cpu_to_le32(arg->bcn_tx_power); 30205e3dd157SKalle Valo 30215e3dd157SKalle Valo if (arg->ssid) { 30225e3dd157SKalle Valo cmd->ssid.ssid_len = __cpu_to_le32(arg->ssid_len); 30235e3dd157SKalle Valo memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len); 30245e3dd157SKalle Valo } 30255e3dd157SKalle Valo 30265e3dd157SKalle Valo cmd->chan.mhz = __cpu_to_le32(arg->channel.freq); 30275e3dd157SKalle Valo 30285e3dd157SKalle Valo cmd->chan.band_center_freq1 = 30295e3dd157SKalle Valo __cpu_to_le32(arg->channel.band_center_freq1); 30305e3dd157SKalle Valo 30315e3dd157SKalle Valo cmd->chan.mode = arg->channel.mode; 3032e8a50f8bSMarek Puzyniak cmd->chan.flags |= __cpu_to_le32(ch_flags); 30335e3dd157SKalle Valo cmd->chan.min_power = arg->channel.min_power; 30345e3dd157SKalle Valo cmd->chan.max_power = arg->channel.max_power; 30355e3dd157SKalle Valo cmd->chan.reg_power = arg->channel.max_reg_power; 30365e3dd157SKalle Valo cmd->chan.reg_classid = arg->channel.reg_class_id; 30375e3dd157SKalle Valo cmd->chan.antenna_max = arg->channel.max_antenna_gain; 30385e3dd157SKalle Valo 30395e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 3040e8a50f8bSMarek Puzyniak "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, " 3041e8a50f8bSMarek Puzyniak "ch_flags: 0x%0X, max_power: %d\n", cmdname, arg->vdev_id, 3042e8a50f8bSMarek Puzyniak flags, arg->channel.freq, arg->channel.mode, 3043e8a50f8bSMarek Puzyniak cmd->chan.flags, arg->channel.max_power); 30445e3dd157SKalle Valo 30455e3dd157SKalle Valo return ath10k_wmi_cmd_send(ar, skb, cmd_id); 30465e3dd157SKalle Valo } 30475e3dd157SKalle Valo 30485e3dd157SKalle Valo int ath10k_wmi_vdev_start(struct ath10k *ar, 30495e3dd157SKalle Valo const struct wmi_vdev_start_request_arg *arg) 30505e3dd157SKalle Valo { 3051ce42870eSBartosz Markowski u32 cmd_id = ar->wmi.cmd->vdev_start_request_cmdid; 3052ce42870eSBartosz Markowski 3053ce42870eSBartosz Markowski return ath10k_wmi_vdev_start_restart(ar, arg, cmd_id); 30545e3dd157SKalle Valo } 30555e3dd157SKalle Valo 30565e3dd157SKalle Valo int ath10k_wmi_vdev_restart(struct ath10k *ar, 30575e3dd157SKalle Valo const struct wmi_vdev_start_request_arg *arg) 30585e3dd157SKalle Valo { 3059ce42870eSBartosz Markowski u32 cmd_id = ar->wmi.cmd->vdev_restart_request_cmdid; 3060ce42870eSBartosz Markowski 3061ce42870eSBartosz Markowski return ath10k_wmi_vdev_start_restart(ar, arg, cmd_id); 30625e3dd157SKalle Valo } 30635e3dd157SKalle Valo 30645e3dd157SKalle Valo int ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id) 30655e3dd157SKalle Valo { 30665e3dd157SKalle Valo struct wmi_vdev_stop_cmd *cmd; 30675e3dd157SKalle Valo struct sk_buff *skb; 30685e3dd157SKalle Valo 30695e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 30705e3dd157SKalle Valo if (!skb) 30715e3dd157SKalle Valo return -ENOMEM; 30725e3dd157SKalle Valo 30735e3dd157SKalle Valo cmd = (struct wmi_vdev_stop_cmd *)skb->data; 30745e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 30755e3dd157SKalle Valo 30765e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi vdev stop id 0x%x\n", vdev_id); 30775e3dd157SKalle Valo 3078ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_stop_cmdid); 30795e3dd157SKalle Valo } 30805e3dd157SKalle Valo 30815e3dd157SKalle Valo int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid) 30825e3dd157SKalle Valo { 30835e3dd157SKalle Valo struct wmi_vdev_up_cmd *cmd; 30845e3dd157SKalle Valo struct sk_buff *skb; 30855e3dd157SKalle Valo 30865e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 30875e3dd157SKalle Valo if (!skb) 30885e3dd157SKalle Valo return -ENOMEM; 30895e3dd157SKalle Valo 30905e3dd157SKalle Valo cmd = (struct wmi_vdev_up_cmd *)skb->data; 30915e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 30925e3dd157SKalle Valo cmd->vdev_assoc_id = __cpu_to_le32(aid); 30937b4371eaSJoe Perches memcpy(&cmd->vdev_bssid.addr, bssid, ETH_ALEN); 30945e3dd157SKalle Valo 30955e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 30965e3dd157SKalle Valo "wmi mgmt vdev up id 0x%x assoc id %d bssid %pM\n", 30975e3dd157SKalle Valo vdev_id, aid, bssid); 30985e3dd157SKalle Valo 3099ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_up_cmdid); 31005e3dd157SKalle Valo } 31015e3dd157SKalle Valo 31025e3dd157SKalle Valo int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id) 31035e3dd157SKalle Valo { 31045e3dd157SKalle Valo struct wmi_vdev_down_cmd *cmd; 31055e3dd157SKalle Valo struct sk_buff *skb; 31065e3dd157SKalle Valo 31075e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 31085e3dd157SKalle Valo if (!skb) 31095e3dd157SKalle Valo return -ENOMEM; 31105e3dd157SKalle Valo 31115e3dd157SKalle Valo cmd = (struct wmi_vdev_down_cmd *)skb->data; 31125e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 31135e3dd157SKalle Valo 31145e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 31155e3dd157SKalle Valo "wmi mgmt vdev down id 0x%x\n", vdev_id); 31165e3dd157SKalle Valo 3117ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_down_cmdid); 31185e3dd157SKalle Valo } 31195e3dd157SKalle Valo 31205e3dd157SKalle Valo int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, 31216d1506e7SBartosz Markowski u32 param_id, u32 param_value) 31225e3dd157SKalle Valo { 31235e3dd157SKalle Valo struct wmi_vdev_set_param_cmd *cmd; 31245e3dd157SKalle Valo struct sk_buff *skb; 31255e3dd157SKalle Valo 31266d1506e7SBartosz Markowski if (param_id == WMI_VDEV_PARAM_UNSUPPORTED) { 31276d1506e7SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, 31286d1506e7SBartosz Markowski "vdev param %d not supported by firmware\n", 31296d1506e7SBartosz Markowski param_id); 3130ebc9abddSBartosz Markowski return -EOPNOTSUPP; 31316d1506e7SBartosz Markowski } 31326d1506e7SBartosz Markowski 31335e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 31345e3dd157SKalle Valo if (!skb) 31355e3dd157SKalle Valo return -ENOMEM; 31365e3dd157SKalle Valo 31375e3dd157SKalle Valo cmd = (struct wmi_vdev_set_param_cmd *)skb->data; 31385e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 31395e3dd157SKalle Valo cmd->param_id = __cpu_to_le32(param_id); 31405e3dd157SKalle Valo cmd->param_value = __cpu_to_le32(param_value); 31415e3dd157SKalle Valo 31425e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 31435e3dd157SKalle Valo "wmi vdev id 0x%x set param %d value %d\n", 31445e3dd157SKalle Valo vdev_id, param_id, param_value); 31455e3dd157SKalle Valo 3146ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_set_param_cmdid); 31475e3dd157SKalle Valo } 31485e3dd157SKalle Valo 31495e3dd157SKalle Valo int ath10k_wmi_vdev_install_key(struct ath10k *ar, 31505e3dd157SKalle Valo const struct wmi_vdev_install_key_arg *arg) 31515e3dd157SKalle Valo { 31525e3dd157SKalle Valo struct wmi_vdev_install_key_cmd *cmd; 31535e3dd157SKalle Valo struct sk_buff *skb; 31545e3dd157SKalle Valo 31555e3dd157SKalle Valo if (arg->key_cipher == WMI_CIPHER_NONE && arg->key_data != NULL) 31565e3dd157SKalle Valo return -EINVAL; 31575e3dd157SKalle Valo if (arg->key_cipher != WMI_CIPHER_NONE && arg->key_data == NULL) 31585e3dd157SKalle Valo return -EINVAL; 31595e3dd157SKalle Valo 31605e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd) + arg->key_len); 31615e3dd157SKalle Valo if (!skb) 31625e3dd157SKalle Valo return -ENOMEM; 31635e3dd157SKalle Valo 31645e3dd157SKalle Valo cmd = (struct wmi_vdev_install_key_cmd *)skb->data; 31655e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(arg->vdev_id); 31665e3dd157SKalle Valo cmd->key_idx = __cpu_to_le32(arg->key_idx); 31675e3dd157SKalle Valo cmd->key_flags = __cpu_to_le32(arg->key_flags); 31685e3dd157SKalle Valo cmd->key_cipher = __cpu_to_le32(arg->key_cipher); 31695e3dd157SKalle Valo cmd->key_len = __cpu_to_le32(arg->key_len); 31705e3dd157SKalle Valo cmd->key_txmic_len = __cpu_to_le32(arg->key_txmic_len); 31715e3dd157SKalle Valo cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len); 31725e3dd157SKalle Valo 31735e3dd157SKalle Valo if (arg->macaddr) 31745e3dd157SKalle Valo memcpy(cmd->peer_macaddr.addr, arg->macaddr, ETH_ALEN); 31755e3dd157SKalle Valo if (arg->key_data) 31765e3dd157SKalle Valo memcpy(cmd->key_data, arg->key_data, arg->key_len); 31775e3dd157SKalle Valo 3178e0c508abSMichal Kazior ath10k_dbg(ATH10K_DBG_WMI, 3179e0c508abSMichal Kazior "wmi vdev install key idx %d cipher %d len %d\n", 3180e0c508abSMichal Kazior arg->key_idx, arg->key_cipher, arg->key_len); 3181ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, 3182ce42870eSBartosz Markowski ar->wmi.cmd->vdev_install_key_cmdid); 31835e3dd157SKalle Valo } 31845e3dd157SKalle Valo 31855e3dd157SKalle Valo int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, 31865e3dd157SKalle Valo const u8 peer_addr[ETH_ALEN]) 31875e3dd157SKalle Valo { 31885e3dd157SKalle Valo struct wmi_peer_create_cmd *cmd; 31895e3dd157SKalle Valo struct sk_buff *skb; 31905e3dd157SKalle Valo 31915e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 31925e3dd157SKalle Valo if (!skb) 31935e3dd157SKalle Valo return -ENOMEM; 31945e3dd157SKalle Valo 31955e3dd157SKalle Valo cmd = (struct wmi_peer_create_cmd *)skb->data; 31965e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 31975e3dd157SKalle Valo memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); 31985e3dd157SKalle Valo 31995e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 32005e3dd157SKalle Valo "wmi peer create vdev_id %d peer_addr %pM\n", 32015e3dd157SKalle Valo vdev_id, peer_addr); 3202ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_create_cmdid); 32035e3dd157SKalle Valo } 32045e3dd157SKalle Valo 32055e3dd157SKalle Valo int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id, 32065e3dd157SKalle Valo const u8 peer_addr[ETH_ALEN]) 32075e3dd157SKalle Valo { 32085e3dd157SKalle Valo struct wmi_peer_delete_cmd *cmd; 32095e3dd157SKalle Valo struct sk_buff *skb; 32105e3dd157SKalle Valo 32115e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 32125e3dd157SKalle Valo if (!skb) 32135e3dd157SKalle Valo return -ENOMEM; 32145e3dd157SKalle Valo 32155e3dd157SKalle Valo cmd = (struct wmi_peer_delete_cmd *)skb->data; 32165e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 32175e3dd157SKalle Valo memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); 32185e3dd157SKalle Valo 32195e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 32205e3dd157SKalle Valo "wmi peer delete vdev_id %d peer_addr %pM\n", 32215e3dd157SKalle Valo vdev_id, peer_addr); 3222ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_delete_cmdid); 32235e3dd157SKalle Valo } 32245e3dd157SKalle Valo 32255e3dd157SKalle Valo int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id, 32265e3dd157SKalle Valo const u8 peer_addr[ETH_ALEN], u32 tid_bitmap) 32275e3dd157SKalle Valo { 32285e3dd157SKalle Valo struct wmi_peer_flush_tids_cmd *cmd; 32295e3dd157SKalle Valo struct sk_buff *skb; 32305e3dd157SKalle Valo 32315e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 32325e3dd157SKalle Valo if (!skb) 32335e3dd157SKalle Valo return -ENOMEM; 32345e3dd157SKalle Valo 32355e3dd157SKalle Valo cmd = (struct wmi_peer_flush_tids_cmd *)skb->data; 32365e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 32375e3dd157SKalle Valo cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap); 32385e3dd157SKalle Valo memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); 32395e3dd157SKalle Valo 32405e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 32415e3dd157SKalle Valo "wmi peer flush vdev_id %d peer_addr %pM tids %08x\n", 32425e3dd157SKalle Valo vdev_id, peer_addr, tid_bitmap); 3243ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_flush_tids_cmdid); 32445e3dd157SKalle Valo } 32455e3dd157SKalle Valo 32465e3dd157SKalle Valo int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, 32475e3dd157SKalle Valo const u8 *peer_addr, enum wmi_peer_param param_id, 32485e3dd157SKalle Valo u32 param_value) 32495e3dd157SKalle Valo { 32505e3dd157SKalle Valo struct wmi_peer_set_param_cmd *cmd; 32515e3dd157SKalle Valo struct sk_buff *skb; 32525e3dd157SKalle Valo 32535e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 32545e3dd157SKalle Valo if (!skb) 32555e3dd157SKalle Valo return -ENOMEM; 32565e3dd157SKalle Valo 32575e3dd157SKalle Valo cmd = (struct wmi_peer_set_param_cmd *)skb->data; 32585e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 32595e3dd157SKalle Valo cmd->param_id = __cpu_to_le32(param_id); 32605e3dd157SKalle Valo cmd->param_value = __cpu_to_le32(param_value); 3261d458cdf7SJoe Perches memcpy(&cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); 32625e3dd157SKalle Valo 32635e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 32645e3dd157SKalle Valo "wmi vdev %d peer 0x%pM set param %d value %d\n", 32655e3dd157SKalle Valo vdev_id, peer_addr, param_id, param_value); 32665e3dd157SKalle Valo 3267ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_set_param_cmdid); 32685e3dd157SKalle Valo } 32695e3dd157SKalle Valo 32705e3dd157SKalle Valo int ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id, 32715e3dd157SKalle Valo enum wmi_sta_ps_mode psmode) 32725e3dd157SKalle Valo { 32735e3dd157SKalle Valo struct wmi_sta_powersave_mode_cmd *cmd; 32745e3dd157SKalle Valo struct sk_buff *skb; 32755e3dd157SKalle Valo 32765e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 32775e3dd157SKalle Valo if (!skb) 32785e3dd157SKalle Valo return -ENOMEM; 32795e3dd157SKalle Valo 32805e3dd157SKalle Valo cmd = (struct wmi_sta_powersave_mode_cmd *)skb->data; 32815e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 32825e3dd157SKalle Valo cmd->sta_ps_mode = __cpu_to_le32(psmode); 32835e3dd157SKalle Valo 32845e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 32855e3dd157SKalle Valo "wmi set powersave id 0x%x mode %d\n", 32865e3dd157SKalle Valo vdev_id, psmode); 32875e3dd157SKalle Valo 3288ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, 3289ce42870eSBartosz Markowski ar->wmi.cmd->sta_powersave_mode_cmdid); 32905e3dd157SKalle Valo } 32915e3dd157SKalle Valo 32925e3dd157SKalle Valo int ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id, 32935e3dd157SKalle Valo enum wmi_sta_powersave_param param_id, 32945e3dd157SKalle Valo u32 value) 32955e3dd157SKalle Valo { 32965e3dd157SKalle Valo struct wmi_sta_powersave_param_cmd *cmd; 32975e3dd157SKalle Valo struct sk_buff *skb; 32985e3dd157SKalle Valo 32995e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 33005e3dd157SKalle Valo if (!skb) 33015e3dd157SKalle Valo return -ENOMEM; 33025e3dd157SKalle Valo 33035e3dd157SKalle Valo cmd = (struct wmi_sta_powersave_param_cmd *)skb->data; 33045e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 33055e3dd157SKalle Valo cmd->param_id = __cpu_to_le32(param_id); 33065e3dd157SKalle Valo cmd->param_value = __cpu_to_le32(value); 33075e3dd157SKalle Valo 33085e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 33095e3dd157SKalle Valo "wmi sta ps param vdev_id 0x%x param %d value %d\n", 33105e3dd157SKalle Valo vdev_id, param_id, value); 3311ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, 3312ce42870eSBartosz Markowski ar->wmi.cmd->sta_powersave_param_cmdid); 33135e3dd157SKalle Valo } 33145e3dd157SKalle Valo 33155e3dd157SKalle Valo int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac, 33165e3dd157SKalle Valo enum wmi_ap_ps_peer_param param_id, u32 value) 33175e3dd157SKalle Valo { 33185e3dd157SKalle Valo struct wmi_ap_ps_peer_cmd *cmd; 33195e3dd157SKalle Valo struct sk_buff *skb; 33205e3dd157SKalle Valo 33215e3dd157SKalle Valo if (!mac) 33225e3dd157SKalle Valo return -EINVAL; 33235e3dd157SKalle Valo 33245e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 33255e3dd157SKalle Valo if (!skb) 33265e3dd157SKalle Valo return -ENOMEM; 33275e3dd157SKalle Valo 33285e3dd157SKalle Valo cmd = (struct wmi_ap_ps_peer_cmd *)skb->data; 33295e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 33305e3dd157SKalle Valo cmd->param_id = __cpu_to_le32(param_id); 33315e3dd157SKalle Valo cmd->param_value = __cpu_to_le32(value); 33325e3dd157SKalle Valo memcpy(&cmd->peer_macaddr, mac, ETH_ALEN); 33335e3dd157SKalle Valo 33345e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 33355e3dd157SKalle Valo "wmi ap ps param vdev_id 0x%X param %d value %d mac_addr %pM\n", 33365e3dd157SKalle Valo vdev_id, param_id, value, mac); 33375e3dd157SKalle Valo 3338ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, 3339ce42870eSBartosz Markowski ar->wmi.cmd->ap_ps_peer_param_cmdid); 33405e3dd157SKalle Valo } 33415e3dd157SKalle Valo 33425e3dd157SKalle Valo int ath10k_wmi_scan_chan_list(struct ath10k *ar, 33435e3dd157SKalle Valo const struct wmi_scan_chan_list_arg *arg) 33445e3dd157SKalle Valo { 33455e3dd157SKalle Valo struct wmi_scan_chan_list_cmd *cmd; 33465e3dd157SKalle Valo struct sk_buff *skb; 33475e3dd157SKalle Valo struct wmi_channel_arg *ch; 33485e3dd157SKalle Valo struct wmi_channel *ci; 33495e3dd157SKalle Valo int len; 33505e3dd157SKalle Valo int i; 33515e3dd157SKalle Valo 33525e3dd157SKalle Valo len = sizeof(*cmd) + arg->n_channels * sizeof(struct wmi_channel); 33535e3dd157SKalle Valo 33545e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(len); 33555e3dd157SKalle Valo if (!skb) 33565e3dd157SKalle Valo return -EINVAL; 33575e3dd157SKalle Valo 33585e3dd157SKalle Valo cmd = (struct wmi_scan_chan_list_cmd *)skb->data; 33595e3dd157SKalle Valo cmd->num_scan_chans = __cpu_to_le32(arg->n_channels); 33605e3dd157SKalle Valo 33615e3dd157SKalle Valo for (i = 0; i < arg->n_channels; i++) { 33625e3dd157SKalle Valo u32 flags = 0; 33635e3dd157SKalle Valo 33645e3dd157SKalle Valo ch = &arg->channels[i]; 33655e3dd157SKalle Valo ci = &cmd->chan_info[i]; 33665e3dd157SKalle Valo 33675e3dd157SKalle Valo if (ch->passive) 33685e3dd157SKalle Valo flags |= WMI_CHAN_FLAG_PASSIVE; 33695e3dd157SKalle Valo if (ch->allow_ibss) 33705e3dd157SKalle Valo flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED; 33715e3dd157SKalle Valo if (ch->allow_ht) 33725e3dd157SKalle Valo flags |= WMI_CHAN_FLAG_ALLOW_HT; 33735e3dd157SKalle Valo if (ch->allow_vht) 33745e3dd157SKalle Valo flags |= WMI_CHAN_FLAG_ALLOW_VHT; 33755e3dd157SKalle Valo if (ch->ht40plus) 33765e3dd157SKalle Valo flags |= WMI_CHAN_FLAG_HT40_PLUS; 3377e8a50f8bSMarek Puzyniak if (ch->chan_radar) 3378e8a50f8bSMarek Puzyniak flags |= WMI_CHAN_FLAG_DFS; 33795e3dd157SKalle Valo 33805e3dd157SKalle Valo ci->mhz = __cpu_to_le32(ch->freq); 33815e3dd157SKalle Valo ci->band_center_freq1 = __cpu_to_le32(ch->freq); 33825e3dd157SKalle Valo ci->band_center_freq2 = 0; 33835e3dd157SKalle Valo ci->min_power = ch->min_power; 33845e3dd157SKalle Valo ci->max_power = ch->max_power; 33855e3dd157SKalle Valo ci->reg_power = ch->max_reg_power; 33865e3dd157SKalle Valo ci->antenna_max = ch->max_antenna_gain; 33875e3dd157SKalle Valo ci->antenna_max = 0; 33885e3dd157SKalle Valo 33895e3dd157SKalle Valo /* mode & flags share storage */ 33905e3dd157SKalle Valo ci->mode = ch->mode; 33915e3dd157SKalle Valo ci->flags |= __cpu_to_le32(flags); 33925e3dd157SKalle Valo } 33935e3dd157SKalle Valo 3394ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid); 33955e3dd157SKalle Valo } 33965e3dd157SKalle Valo 33975e3dd157SKalle Valo int ath10k_wmi_peer_assoc(struct ath10k *ar, 33985e3dd157SKalle Valo const struct wmi_peer_assoc_complete_arg *arg) 33995e3dd157SKalle Valo { 34005e3dd157SKalle Valo struct wmi_peer_assoc_complete_cmd *cmd; 34015e3dd157SKalle Valo struct sk_buff *skb; 34025e3dd157SKalle Valo 34035e3dd157SKalle Valo if (arg->peer_mpdu_density > 16) 34045e3dd157SKalle Valo return -EINVAL; 34055e3dd157SKalle Valo if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES) 34065e3dd157SKalle Valo return -EINVAL; 34075e3dd157SKalle Valo if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES) 34085e3dd157SKalle Valo return -EINVAL; 34095e3dd157SKalle Valo 34105e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 34115e3dd157SKalle Valo if (!skb) 34125e3dd157SKalle Valo return -ENOMEM; 34135e3dd157SKalle Valo 34145e3dd157SKalle Valo cmd = (struct wmi_peer_assoc_complete_cmd *)skb->data; 34155e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(arg->vdev_id); 34165e3dd157SKalle Valo cmd->peer_new_assoc = __cpu_to_le32(arg->peer_reassoc ? 0 : 1); 34175e3dd157SKalle Valo cmd->peer_associd = __cpu_to_le32(arg->peer_aid); 34185e3dd157SKalle Valo cmd->peer_flags = __cpu_to_le32(arg->peer_flags); 34195e3dd157SKalle Valo cmd->peer_caps = __cpu_to_le32(arg->peer_caps); 34205e3dd157SKalle Valo cmd->peer_listen_intval = __cpu_to_le32(arg->peer_listen_intval); 34215e3dd157SKalle Valo cmd->peer_ht_caps = __cpu_to_le32(arg->peer_ht_caps); 34225e3dd157SKalle Valo cmd->peer_max_mpdu = __cpu_to_le32(arg->peer_max_mpdu); 34235e3dd157SKalle Valo cmd->peer_mpdu_density = __cpu_to_le32(arg->peer_mpdu_density); 34245e3dd157SKalle Valo cmd->peer_rate_caps = __cpu_to_le32(arg->peer_rate_caps); 34255e3dd157SKalle Valo cmd->peer_nss = __cpu_to_le32(arg->peer_num_spatial_streams); 34265e3dd157SKalle Valo cmd->peer_vht_caps = __cpu_to_le32(arg->peer_vht_caps); 34275e3dd157SKalle Valo cmd->peer_phymode = __cpu_to_le32(arg->peer_phymode); 34285e3dd157SKalle Valo 34295e3dd157SKalle Valo memcpy(cmd->peer_macaddr.addr, arg->addr, ETH_ALEN); 34305e3dd157SKalle Valo 34315e3dd157SKalle Valo cmd->peer_legacy_rates.num_rates = 34325e3dd157SKalle Valo __cpu_to_le32(arg->peer_legacy_rates.num_rates); 34335e3dd157SKalle Valo memcpy(cmd->peer_legacy_rates.rates, arg->peer_legacy_rates.rates, 34345e3dd157SKalle Valo arg->peer_legacy_rates.num_rates); 34355e3dd157SKalle Valo 34365e3dd157SKalle Valo cmd->peer_ht_rates.num_rates = 34375e3dd157SKalle Valo __cpu_to_le32(arg->peer_ht_rates.num_rates); 34385e3dd157SKalle Valo memcpy(cmd->peer_ht_rates.rates, arg->peer_ht_rates.rates, 34395e3dd157SKalle Valo arg->peer_ht_rates.num_rates); 34405e3dd157SKalle Valo 34415e3dd157SKalle Valo cmd->peer_vht_rates.rx_max_rate = 34425e3dd157SKalle Valo __cpu_to_le32(arg->peer_vht_rates.rx_max_rate); 34435e3dd157SKalle Valo cmd->peer_vht_rates.rx_mcs_set = 34445e3dd157SKalle Valo __cpu_to_le32(arg->peer_vht_rates.rx_mcs_set); 34455e3dd157SKalle Valo cmd->peer_vht_rates.tx_max_rate = 34465e3dd157SKalle Valo __cpu_to_le32(arg->peer_vht_rates.tx_max_rate); 34475e3dd157SKalle Valo cmd->peer_vht_rates.tx_mcs_set = 34485e3dd157SKalle Valo __cpu_to_le32(arg->peer_vht_rates.tx_mcs_set); 34495e3dd157SKalle Valo 3450e0c508abSMichal Kazior ath10k_dbg(ATH10K_DBG_WMI, 3451e0c508abSMichal Kazior "wmi peer assoc vdev %d addr %pM\n", 3452e0c508abSMichal Kazior arg->vdev_id, arg->addr); 3453ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_assoc_cmdid); 34545e3dd157SKalle Valo } 34555e3dd157SKalle Valo 3456748afc47SMichal Kazior /* This function assumes the beacon is already DMA mapped */ 3457748afc47SMichal Kazior int ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif) 34585e3dd157SKalle Valo { 3459748afc47SMichal Kazior struct wmi_bcn_tx_ref_cmd *cmd; 34605e3dd157SKalle Valo struct sk_buff *skb; 3461748afc47SMichal Kazior struct sk_buff *beacon = arvif->beacon; 3462748afc47SMichal Kazior struct ath10k *ar = arvif->ar; 3463748afc47SMichal Kazior struct ieee80211_hdr *hdr; 3464e2045481SMichal Kazior int ret; 3465748afc47SMichal Kazior u16 fc; 34665e3dd157SKalle Valo 3467748afc47SMichal Kazior skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 34685e3dd157SKalle Valo if (!skb) 34695e3dd157SKalle Valo return -ENOMEM; 34705e3dd157SKalle Valo 3471748afc47SMichal Kazior hdr = (struct ieee80211_hdr *)beacon->data; 3472748afc47SMichal Kazior fc = le16_to_cpu(hdr->frame_control); 34735e3dd157SKalle Valo 3474748afc47SMichal Kazior cmd = (struct wmi_bcn_tx_ref_cmd *)skb->data; 3475748afc47SMichal Kazior cmd->vdev_id = __cpu_to_le32(arvif->vdev_id); 3476748afc47SMichal Kazior cmd->data_len = __cpu_to_le32(beacon->len); 3477748afc47SMichal Kazior cmd->data_ptr = __cpu_to_le32(ATH10K_SKB_CB(beacon)->paddr); 3478748afc47SMichal Kazior cmd->msdu_id = 0; 3479748afc47SMichal Kazior cmd->frame_control = __cpu_to_le32(fc); 3480748afc47SMichal Kazior cmd->flags = 0; 3481748afc47SMichal Kazior 3482748afc47SMichal Kazior if (ATH10K_SKB_CB(beacon)->bcn.dtim_zero) 3483748afc47SMichal Kazior cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO); 3484748afc47SMichal Kazior 3485748afc47SMichal Kazior if (ATH10K_SKB_CB(beacon)->bcn.deliver_cab) 3486748afc47SMichal Kazior cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB); 3487748afc47SMichal Kazior 3488748afc47SMichal Kazior ret = ath10k_wmi_cmd_send_nowait(ar, skb, 3489748afc47SMichal Kazior ar->wmi.cmd->pdev_send_bcn_cmdid); 3490748afc47SMichal Kazior 3491e2045481SMichal Kazior if (ret) 3492e2045481SMichal Kazior dev_kfree_skb(skb); 3493e2045481SMichal Kazior 3494e2045481SMichal Kazior return ret; 34955e3dd157SKalle Valo } 34965e3dd157SKalle Valo 34975e3dd157SKalle Valo static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params, 34985e3dd157SKalle Valo const struct wmi_wmm_params_arg *arg) 34995e3dd157SKalle Valo { 35005e3dd157SKalle Valo params->cwmin = __cpu_to_le32(arg->cwmin); 35015e3dd157SKalle Valo params->cwmax = __cpu_to_le32(arg->cwmax); 35025e3dd157SKalle Valo params->aifs = __cpu_to_le32(arg->aifs); 35035e3dd157SKalle Valo params->txop = __cpu_to_le32(arg->txop); 35045e3dd157SKalle Valo params->acm = __cpu_to_le32(arg->acm); 35055e3dd157SKalle Valo params->no_ack = __cpu_to_le32(arg->no_ack); 35065e3dd157SKalle Valo } 35075e3dd157SKalle Valo 35085e3dd157SKalle Valo int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, 35095e3dd157SKalle Valo const struct wmi_pdev_set_wmm_params_arg *arg) 35105e3dd157SKalle Valo { 35115e3dd157SKalle Valo struct wmi_pdev_set_wmm_params *cmd; 35125e3dd157SKalle Valo struct sk_buff *skb; 35135e3dd157SKalle Valo 35145e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 35155e3dd157SKalle Valo if (!skb) 35165e3dd157SKalle Valo return -ENOMEM; 35175e3dd157SKalle Valo 35185e3dd157SKalle Valo cmd = (struct wmi_pdev_set_wmm_params *)skb->data; 35195e3dd157SKalle Valo ath10k_wmi_pdev_set_wmm_param(&cmd->ac_be, &arg->ac_be); 35205e3dd157SKalle Valo ath10k_wmi_pdev_set_wmm_param(&cmd->ac_bk, &arg->ac_bk); 35215e3dd157SKalle Valo ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vi, &arg->ac_vi); 35225e3dd157SKalle Valo ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vo, &arg->ac_vo); 35235e3dd157SKalle Valo 35245e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set wmm params\n"); 3525ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, 3526ce42870eSBartosz Markowski ar->wmi.cmd->pdev_set_wmm_params_cmdid); 35275e3dd157SKalle Valo } 35285e3dd157SKalle Valo 35295e3dd157SKalle Valo int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id) 35305e3dd157SKalle Valo { 35315e3dd157SKalle Valo struct wmi_request_stats_cmd *cmd; 35325e3dd157SKalle Valo struct sk_buff *skb; 35335e3dd157SKalle Valo 35345e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 35355e3dd157SKalle Valo if (!skb) 35365e3dd157SKalle Valo return -ENOMEM; 35375e3dd157SKalle Valo 35385e3dd157SKalle Valo cmd = (struct wmi_request_stats_cmd *)skb->data; 35395e3dd157SKalle Valo cmd->stats_id = __cpu_to_le32(stats_id); 35405e3dd157SKalle Valo 35415e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi request stats %d\n", (int)stats_id); 3542ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->request_stats_cmdid); 35435e3dd157SKalle Valo } 35449cfbce75SMichal Kazior 35459cfbce75SMichal Kazior int ath10k_wmi_force_fw_hang(struct ath10k *ar, 35469cfbce75SMichal Kazior enum wmi_force_fw_hang_type type, u32 delay_ms) 35479cfbce75SMichal Kazior { 35489cfbce75SMichal Kazior struct wmi_force_fw_hang_cmd *cmd; 35499cfbce75SMichal Kazior struct sk_buff *skb; 35509cfbce75SMichal Kazior 35519cfbce75SMichal Kazior skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 35529cfbce75SMichal Kazior if (!skb) 35539cfbce75SMichal Kazior return -ENOMEM; 35549cfbce75SMichal Kazior 35559cfbce75SMichal Kazior cmd = (struct wmi_force_fw_hang_cmd *)skb->data; 35569cfbce75SMichal Kazior cmd->type = __cpu_to_le32(type); 35579cfbce75SMichal Kazior cmd->delay_ms = __cpu_to_le32(delay_ms); 35589cfbce75SMichal Kazior 35599cfbce75SMichal Kazior ath10k_dbg(ATH10K_DBG_WMI, "wmi force fw hang %d delay %d\n", 35609cfbce75SMichal Kazior type, delay_ms); 3561ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid); 35629cfbce75SMichal Kazior } 3563f118a3e5SKalle Valo 3564f118a3e5SKalle Valo int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable) 3565f118a3e5SKalle Valo { 3566f118a3e5SKalle Valo struct wmi_dbglog_cfg_cmd *cmd; 3567f118a3e5SKalle Valo struct sk_buff *skb; 3568f118a3e5SKalle Valo u32 cfg; 3569f118a3e5SKalle Valo 3570f118a3e5SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 3571f118a3e5SKalle Valo if (!skb) 3572f118a3e5SKalle Valo return -ENOMEM; 3573f118a3e5SKalle Valo 3574f118a3e5SKalle Valo cmd = (struct wmi_dbglog_cfg_cmd *)skb->data; 3575f118a3e5SKalle Valo 3576f118a3e5SKalle Valo if (module_enable) { 3577f118a3e5SKalle Valo cfg = SM(ATH10K_DBGLOG_LEVEL_VERBOSE, 3578f118a3e5SKalle Valo ATH10K_DBGLOG_CFG_LOG_LVL); 3579f118a3e5SKalle Valo } else { 3580f118a3e5SKalle Valo /* set back defaults, all modules with WARN level */ 3581f118a3e5SKalle Valo cfg = SM(ATH10K_DBGLOG_LEVEL_WARN, 3582f118a3e5SKalle Valo ATH10K_DBGLOG_CFG_LOG_LVL); 3583f118a3e5SKalle Valo module_enable = ~0; 3584f118a3e5SKalle Valo } 3585f118a3e5SKalle Valo 3586f118a3e5SKalle Valo cmd->module_enable = __cpu_to_le32(module_enable); 3587f118a3e5SKalle Valo cmd->module_valid = __cpu_to_le32(~0); 3588f118a3e5SKalle Valo cmd->config_enable = __cpu_to_le32(cfg); 3589f118a3e5SKalle Valo cmd->config_valid = __cpu_to_le32(ATH10K_DBGLOG_CFG_LOG_LVL_MASK); 3590f118a3e5SKalle Valo 3591f118a3e5SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 3592f118a3e5SKalle Valo "wmi dbglog cfg modules %08x %08x config %08x %08x\n", 3593f118a3e5SKalle Valo __le32_to_cpu(cmd->module_enable), 3594f118a3e5SKalle Valo __le32_to_cpu(cmd->module_valid), 3595f118a3e5SKalle Valo __le32_to_cpu(cmd->config_enable), 3596f118a3e5SKalle Valo __le32_to_cpu(cmd->config_valid)); 3597f118a3e5SKalle Valo 3598f118a3e5SKalle Valo return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->dbglog_cfg_cmdid); 3599f118a3e5SKalle Valo } 3600