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> 195e3dd157SKalle Valo 205e3dd157SKalle Valo #include "core.h" 215e3dd157SKalle Valo #include "htc.h" 225e3dd157SKalle Valo #include "debug.h" 235e3dd157SKalle Valo #include "wmi.h" 245e3dd157SKalle Valo #include "mac.h" 255e3dd157SKalle Valo 26ce42870eSBartosz Markowski /* MAIN WMI cmd track */ 27ce42870eSBartosz Markowski static struct wmi_cmd_map wmi_cmd_map = { 28ce42870eSBartosz Markowski .init_cmdid = WMI_INIT_CMDID, 29ce42870eSBartosz Markowski .start_scan_cmdid = WMI_START_SCAN_CMDID, 30ce42870eSBartosz Markowski .stop_scan_cmdid = WMI_STOP_SCAN_CMDID, 31ce42870eSBartosz Markowski .scan_chan_list_cmdid = WMI_SCAN_CHAN_LIST_CMDID, 32ce42870eSBartosz Markowski .scan_sch_prio_tbl_cmdid = WMI_SCAN_SCH_PRIO_TBL_CMDID, 33ce42870eSBartosz Markowski .pdev_set_regdomain_cmdid = WMI_PDEV_SET_REGDOMAIN_CMDID, 34ce42870eSBartosz Markowski .pdev_set_channel_cmdid = WMI_PDEV_SET_CHANNEL_CMDID, 35ce42870eSBartosz Markowski .pdev_set_param_cmdid = WMI_PDEV_SET_PARAM_CMDID, 36ce42870eSBartosz Markowski .pdev_pktlog_enable_cmdid = WMI_PDEV_PKTLOG_ENABLE_CMDID, 37ce42870eSBartosz Markowski .pdev_pktlog_disable_cmdid = WMI_PDEV_PKTLOG_DISABLE_CMDID, 38ce42870eSBartosz Markowski .pdev_set_wmm_params_cmdid = WMI_PDEV_SET_WMM_PARAMS_CMDID, 39ce42870eSBartosz Markowski .pdev_set_ht_cap_ie_cmdid = WMI_PDEV_SET_HT_CAP_IE_CMDID, 40ce42870eSBartosz Markowski .pdev_set_vht_cap_ie_cmdid = WMI_PDEV_SET_VHT_CAP_IE_CMDID, 41ce42870eSBartosz Markowski .pdev_set_dscp_tid_map_cmdid = WMI_PDEV_SET_DSCP_TID_MAP_CMDID, 42ce42870eSBartosz Markowski .pdev_set_quiet_mode_cmdid = WMI_PDEV_SET_QUIET_MODE_CMDID, 43ce42870eSBartosz Markowski .pdev_green_ap_ps_enable_cmdid = WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID, 44ce42870eSBartosz Markowski .pdev_get_tpc_config_cmdid = WMI_PDEV_GET_TPC_CONFIG_CMDID, 45ce42870eSBartosz Markowski .pdev_set_base_macaddr_cmdid = WMI_PDEV_SET_BASE_MACADDR_CMDID, 46ce42870eSBartosz Markowski .vdev_create_cmdid = WMI_VDEV_CREATE_CMDID, 47ce42870eSBartosz Markowski .vdev_delete_cmdid = WMI_VDEV_DELETE_CMDID, 48ce42870eSBartosz Markowski .vdev_start_request_cmdid = WMI_VDEV_START_REQUEST_CMDID, 49ce42870eSBartosz Markowski .vdev_restart_request_cmdid = WMI_VDEV_RESTART_REQUEST_CMDID, 50ce42870eSBartosz Markowski .vdev_up_cmdid = WMI_VDEV_UP_CMDID, 51ce42870eSBartosz Markowski .vdev_stop_cmdid = WMI_VDEV_STOP_CMDID, 52ce42870eSBartosz Markowski .vdev_down_cmdid = WMI_VDEV_DOWN_CMDID, 53ce42870eSBartosz Markowski .vdev_set_param_cmdid = WMI_VDEV_SET_PARAM_CMDID, 54ce42870eSBartosz Markowski .vdev_install_key_cmdid = WMI_VDEV_INSTALL_KEY_CMDID, 55ce42870eSBartosz Markowski .peer_create_cmdid = WMI_PEER_CREATE_CMDID, 56ce42870eSBartosz Markowski .peer_delete_cmdid = WMI_PEER_DELETE_CMDID, 57ce42870eSBartosz Markowski .peer_flush_tids_cmdid = WMI_PEER_FLUSH_TIDS_CMDID, 58ce42870eSBartosz Markowski .peer_set_param_cmdid = WMI_PEER_SET_PARAM_CMDID, 59ce42870eSBartosz Markowski .peer_assoc_cmdid = WMI_PEER_ASSOC_CMDID, 60ce42870eSBartosz Markowski .peer_add_wds_entry_cmdid = WMI_PEER_ADD_WDS_ENTRY_CMDID, 61ce42870eSBartosz Markowski .peer_remove_wds_entry_cmdid = WMI_PEER_REMOVE_WDS_ENTRY_CMDID, 62ce42870eSBartosz Markowski .peer_mcast_group_cmdid = WMI_PEER_MCAST_GROUP_CMDID, 63ce42870eSBartosz Markowski .bcn_tx_cmdid = WMI_BCN_TX_CMDID, 64ce42870eSBartosz Markowski .pdev_send_bcn_cmdid = WMI_PDEV_SEND_BCN_CMDID, 65ce42870eSBartosz Markowski .bcn_tmpl_cmdid = WMI_BCN_TMPL_CMDID, 66ce42870eSBartosz Markowski .bcn_filter_rx_cmdid = WMI_BCN_FILTER_RX_CMDID, 67ce42870eSBartosz Markowski .prb_req_filter_rx_cmdid = WMI_PRB_REQ_FILTER_RX_CMDID, 68ce42870eSBartosz Markowski .mgmt_tx_cmdid = WMI_MGMT_TX_CMDID, 69ce42870eSBartosz Markowski .prb_tmpl_cmdid = WMI_PRB_TMPL_CMDID, 70ce42870eSBartosz Markowski .addba_clear_resp_cmdid = WMI_ADDBA_CLEAR_RESP_CMDID, 71ce42870eSBartosz Markowski .addba_send_cmdid = WMI_ADDBA_SEND_CMDID, 72ce42870eSBartosz Markowski .addba_status_cmdid = WMI_ADDBA_STATUS_CMDID, 73ce42870eSBartosz Markowski .delba_send_cmdid = WMI_DELBA_SEND_CMDID, 74ce42870eSBartosz Markowski .addba_set_resp_cmdid = WMI_ADDBA_SET_RESP_CMDID, 75ce42870eSBartosz Markowski .send_singleamsdu_cmdid = WMI_SEND_SINGLEAMSDU_CMDID, 76ce42870eSBartosz Markowski .sta_powersave_mode_cmdid = WMI_STA_POWERSAVE_MODE_CMDID, 77ce42870eSBartosz Markowski .sta_powersave_param_cmdid = WMI_STA_POWERSAVE_PARAM_CMDID, 78ce42870eSBartosz Markowski .sta_mimo_ps_mode_cmdid = WMI_STA_MIMO_PS_MODE_CMDID, 79ce42870eSBartosz Markowski .pdev_dfs_enable_cmdid = WMI_PDEV_DFS_ENABLE_CMDID, 80ce42870eSBartosz Markowski .pdev_dfs_disable_cmdid = WMI_PDEV_DFS_DISABLE_CMDID, 81ce42870eSBartosz Markowski .roam_scan_mode = WMI_ROAM_SCAN_MODE, 82ce42870eSBartosz Markowski .roam_scan_rssi_threshold = WMI_ROAM_SCAN_RSSI_THRESHOLD, 83ce42870eSBartosz Markowski .roam_scan_period = WMI_ROAM_SCAN_PERIOD, 84ce42870eSBartosz Markowski .roam_scan_rssi_change_threshold = WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD, 85ce42870eSBartosz Markowski .roam_ap_profile = WMI_ROAM_AP_PROFILE, 86ce42870eSBartosz Markowski .ofl_scan_add_ap_profile = WMI_ROAM_AP_PROFILE, 87ce42870eSBartosz Markowski .ofl_scan_remove_ap_profile = WMI_OFL_SCAN_REMOVE_AP_PROFILE, 88ce42870eSBartosz Markowski .ofl_scan_period = WMI_OFL_SCAN_PERIOD, 89ce42870eSBartosz Markowski .p2p_dev_set_device_info = WMI_P2P_DEV_SET_DEVICE_INFO, 90ce42870eSBartosz Markowski .p2p_dev_set_discoverability = WMI_P2P_DEV_SET_DISCOVERABILITY, 91ce42870eSBartosz Markowski .p2p_go_set_beacon_ie = WMI_P2P_GO_SET_BEACON_IE, 92ce42870eSBartosz Markowski .p2p_go_set_probe_resp_ie = WMI_P2P_GO_SET_PROBE_RESP_IE, 93ce42870eSBartosz Markowski .p2p_set_vendor_ie_data_cmdid = WMI_P2P_SET_VENDOR_IE_DATA_CMDID, 94ce42870eSBartosz Markowski .ap_ps_peer_param_cmdid = WMI_AP_PS_PEER_PARAM_CMDID, 95ce42870eSBartosz Markowski .ap_ps_peer_uapsd_coex_cmdid = WMI_AP_PS_PEER_UAPSD_COEX_CMDID, 96ce42870eSBartosz Markowski .peer_rate_retry_sched_cmdid = WMI_PEER_RATE_RETRY_SCHED_CMDID, 97ce42870eSBartosz Markowski .wlan_profile_trigger_cmdid = WMI_WLAN_PROFILE_TRIGGER_CMDID, 98ce42870eSBartosz Markowski .wlan_profile_set_hist_intvl_cmdid = 99ce42870eSBartosz Markowski WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, 100ce42870eSBartosz Markowski .wlan_profile_get_profile_data_cmdid = 101ce42870eSBartosz Markowski WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, 102ce42870eSBartosz Markowski .wlan_profile_enable_profile_id_cmdid = 103ce42870eSBartosz Markowski WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, 104ce42870eSBartosz Markowski .wlan_profile_list_profile_id_cmdid = 105ce42870eSBartosz Markowski WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, 106ce42870eSBartosz Markowski .pdev_suspend_cmdid = WMI_PDEV_SUSPEND_CMDID, 107ce42870eSBartosz Markowski .pdev_resume_cmdid = WMI_PDEV_RESUME_CMDID, 108ce42870eSBartosz Markowski .add_bcn_filter_cmdid = WMI_ADD_BCN_FILTER_CMDID, 109ce42870eSBartosz Markowski .rmv_bcn_filter_cmdid = WMI_RMV_BCN_FILTER_CMDID, 110ce42870eSBartosz Markowski .wow_add_wake_pattern_cmdid = WMI_WOW_ADD_WAKE_PATTERN_CMDID, 111ce42870eSBartosz Markowski .wow_del_wake_pattern_cmdid = WMI_WOW_DEL_WAKE_PATTERN_CMDID, 112ce42870eSBartosz Markowski .wow_enable_disable_wake_event_cmdid = 113ce42870eSBartosz Markowski WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, 114ce42870eSBartosz Markowski .wow_enable_cmdid = WMI_WOW_ENABLE_CMDID, 115ce42870eSBartosz Markowski .wow_hostwakeup_from_sleep_cmdid = WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, 116ce42870eSBartosz Markowski .rtt_measreq_cmdid = WMI_RTT_MEASREQ_CMDID, 117ce42870eSBartosz Markowski .rtt_tsf_cmdid = WMI_RTT_TSF_CMDID, 118ce42870eSBartosz Markowski .vdev_spectral_scan_configure_cmdid = 119ce42870eSBartosz Markowski WMI_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID, 120ce42870eSBartosz Markowski .vdev_spectral_scan_enable_cmdid = WMI_VDEV_SPECTRAL_SCAN_ENABLE_CMDID, 121ce42870eSBartosz Markowski .request_stats_cmdid = WMI_REQUEST_STATS_CMDID, 122ce42870eSBartosz Markowski .set_arp_ns_offload_cmdid = WMI_SET_ARP_NS_OFFLOAD_CMDID, 123ce42870eSBartosz Markowski .network_list_offload_config_cmdid = 124ce42870eSBartosz Markowski WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID, 125ce42870eSBartosz Markowski .gtk_offload_cmdid = WMI_GTK_OFFLOAD_CMDID, 126ce42870eSBartosz Markowski .csa_offload_enable_cmdid = WMI_CSA_OFFLOAD_ENABLE_CMDID, 127ce42870eSBartosz Markowski .csa_offload_chanswitch_cmdid = WMI_CSA_OFFLOAD_CHANSWITCH_CMDID, 128ce42870eSBartosz Markowski .chatter_set_mode_cmdid = WMI_CHATTER_SET_MODE_CMDID, 129ce42870eSBartosz Markowski .peer_tid_addba_cmdid = WMI_PEER_TID_ADDBA_CMDID, 130ce42870eSBartosz Markowski .peer_tid_delba_cmdid = WMI_PEER_TID_DELBA_CMDID, 131ce42870eSBartosz Markowski .sta_dtim_ps_method_cmdid = WMI_STA_DTIM_PS_METHOD_CMDID, 132ce42870eSBartosz Markowski .sta_uapsd_auto_trig_cmdid = WMI_STA_UAPSD_AUTO_TRIG_CMDID, 133ce42870eSBartosz Markowski .sta_keepalive_cmd = WMI_STA_KEEPALIVE_CMD, 134ce42870eSBartosz Markowski .echo_cmdid = WMI_ECHO_CMDID, 135ce42870eSBartosz Markowski .pdev_utf_cmdid = WMI_PDEV_UTF_CMDID, 136ce42870eSBartosz Markowski .dbglog_cfg_cmdid = WMI_DBGLOG_CFG_CMDID, 137ce42870eSBartosz Markowski .pdev_qvit_cmdid = WMI_PDEV_QVIT_CMDID, 138ce42870eSBartosz Markowski .pdev_ftm_intg_cmdid = WMI_PDEV_FTM_INTG_CMDID, 139ce42870eSBartosz Markowski .vdev_set_keepalive_cmdid = WMI_VDEV_SET_KEEPALIVE_CMDID, 140ce42870eSBartosz Markowski .vdev_get_keepalive_cmdid = WMI_VDEV_GET_KEEPALIVE_CMDID, 141ce42870eSBartosz Markowski .force_fw_hang_cmdid = WMI_FORCE_FW_HANG_CMDID, 142ce42870eSBartosz Markowski .gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID, 143ce42870eSBartosz Markowski .gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID, 144ce42870eSBartosz Markowski }; 145ce42870eSBartosz Markowski 146b7e3adf9SBartosz Markowski /* 10.X WMI cmd track */ 147b7e3adf9SBartosz Markowski static struct wmi_cmd_map wmi_10x_cmd_map = { 148b7e3adf9SBartosz Markowski .init_cmdid = WMI_10X_INIT_CMDID, 149b7e3adf9SBartosz Markowski .start_scan_cmdid = WMI_10X_START_SCAN_CMDID, 150b7e3adf9SBartosz Markowski .stop_scan_cmdid = WMI_10X_STOP_SCAN_CMDID, 151b7e3adf9SBartosz Markowski .scan_chan_list_cmdid = WMI_10X_SCAN_CHAN_LIST_CMDID, 15234957b25SBartosz Markowski .scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED, 153b7e3adf9SBartosz Markowski .pdev_set_regdomain_cmdid = WMI_10X_PDEV_SET_REGDOMAIN_CMDID, 154b7e3adf9SBartosz Markowski .pdev_set_channel_cmdid = WMI_10X_PDEV_SET_CHANNEL_CMDID, 155b7e3adf9SBartosz Markowski .pdev_set_param_cmdid = WMI_10X_PDEV_SET_PARAM_CMDID, 156b7e3adf9SBartosz Markowski .pdev_pktlog_enable_cmdid = WMI_10X_PDEV_PKTLOG_ENABLE_CMDID, 157b7e3adf9SBartosz Markowski .pdev_pktlog_disable_cmdid = WMI_10X_PDEV_PKTLOG_DISABLE_CMDID, 158b7e3adf9SBartosz Markowski .pdev_set_wmm_params_cmdid = WMI_10X_PDEV_SET_WMM_PARAMS_CMDID, 159b7e3adf9SBartosz Markowski .pdev_set_ht_cap_ie_cmdid = WMI_10X_PDEV_SET_HT_CAP_IE_CMDID, 160b7e3adf9SBartosz Markowski .pdev_set_vht_cap_ie_cmdid = WMI_10X_PDEV_SET_VHT_CAP_IE_CMDID, 161b7e3adf9SBartosz Markowski .pdev_set_dscp_tid_map_cmdid = WMI_10X_PDEV_SET_DSCP_TID_MAP_CMDID, 162b7e3adf9SBartosz Markowski .pdev_set_quiet_mode_cmdid = WMI_10X_PDEV_SET_QUIET_MODE_CMDID, 163b7e3adf9SBartosz Markowski .pdev_green_ap_ps_enable_cmdid = WMI_10X_PDEV_GREEN_AP_PS_ENABLE_CMDID, 164b7e3adf9SBartosz Markowski .pdev_get_tpc_config_cmdid = WMI_10X_PDEV_GET_TPC_CONFIG_CMDID, 165b7e3adf9SBartosz Markowski .pdev_set_base_macaddr_cmdid = WMI_10X_PDEV_SET_BASE_MACADDR_CMDID, 166b7e3adf9SBartosz Markowski .vdev_create_cmdid = WMI_10X_VDEV_CREATE_CMDID, 167b7e3adf9SBartosz Markowski .vdev_delete_cmdid = WMI_10X_VDEV_DELETE_CMDID, 168b7e3adf9SBartosz Markowski .vdev_start_request_cmdid = WMI_10X_VDEV_START_REQUEST_CMDID, 169b7e3adf9SBartosz Markowski .vdev_restart_request_cmdid = WMI_10X_VDEV_RESTART_REQUEST_CMDID, 170b7e3adf9SBartosz Markowski .vdev_up_cmdid = WMI_10X_VDEV_UP_CMDID, 171b7e3adf9SBartosz Markowski .vdev_stop_cmdid = WMI_10X_VDEV_STOP_CMDID, 172b7e3adf9SBartosz Markowski .vdev_down_cmdid = WMI_10X_VDEV_DOWN_CMDID, 173b7e3adf9SBartosz Markowski .vdev_set_param_cmdid = WMI_10X_VDEV_SET_PARAM_CMDID, 174b7e3adf9SBartosz Markowski .vdev_install_key_cmdid = WMI_10X_VDEV_INSTALL_KEY_CMDID, 175b7e3adf9SBartosz Markowski .peer_create_cmdid = WMI_10X_PEER_CREATE_CMDID, 176b7e3adf9SBartosz Markowski .peer_delete_cmdid = WMI_10X_PEER_DELETE_CMDID, 177b7e3adf9SBartosz Markowski .peer_flush_tids_cmdid = WMI_10X_PEER_FLUSH_TIDS_CMDID, 178b7e3adf9SBartosz Markowski .peer_set_param_cmdid = WMI_10X_PEER_SET_PARAM_CMDID, 179b7e3adf9SBartosz Markowski .peer_assoc_cmdid = WMI_10X_PEER_ASSOC_CMDID, 180b7e3adf9SBartosz Markowski .peer_add_wds_entry_cmdid = WMI_10X_PEER_ADD_WDS_ENTRY_CMDID, 181b7e3adf9SBartosz Markowski .peer_remove_wds_entry_cmdid = WMI_10X_PEER_REMOVE_WDS_ENTRY_CMDID, 182b7e3adf9SBartosz Markowski .peer_mcast_group_cmdid = WMI_10X_PEER_MCAST_GROUP_CMDID, 183b7e3adf9SBartosz Markowski .bcn_tx_cmdid = WMI_10X_BCN_TX_CMDID, 184b7e3adf9SBartosz Markowski .pdev_send_bcn_cmdid = WMI_10X_PDEV_SEND_BCN_CMDID, 18534957b25SBartosz Markowski .bcn_tmpl_cmdid = WMI_CMD_UNSUPPORTED, 186b7e3adf9SBartosz Markowski .bcn_filter_rx_cmdid = WMI_10X_BCN_FILTER_RX_CMDID, 187b7e3adf9SBartosz Markowski .prb_req_filter_rx_cmdid = WMI_10X_PRB_REQ_FILTER_RX_CMDID, 188b7e3adf9SBartosz Markowski .mgmt_tx_cmdid = WMI_10X_MGMT_TX_CMDID, 18934957b25SBartosz Markowski .prb_tmpl_cmdid = WMI_CMD_UNSUPPORTED, 190b7e3adf9SBartosz Markowski .addba_clear_resp_cmdid = WMI_10X_ADDBA_CLEAR_RESP_CMDID, 191b7e3adf9SBartosz Markowski .addba_send_cmdid = WMI_10X_ADDBA_SEND_CMDID, 192b7e3adf9SBartosz Markowski .addba_status_cmdid = WMI_10X_ADDBA_STATUS_CMDID, 193b7e3adf9SBartosz Markowski .delba_send_cmdid = WMI_10X_DELBA_SEND_CMDID, 194b7e3adf9SBartosz Markowski .addba_set_resp_cmdid = WMI_10X_ADDBA_SET_RESP_CMDID, 195b7e3adf9SBartosz Markowski .send_singleamsdu_cmdid = WMI_10X_SEND_SINGLEAMSDU_CMDID, 196b7e3adf9SBartosz Markowski .sta_powersave_mode_cmdid = WMI_10X_STA_POWERSAVE_MODE_CMDID, 197b7e3adf9SBartosz Markowski .sta_powersave_param_cmdid = WMI_10X_STA_POWERSAVE_PARAM_CMDID, 198b7e3adf9SBartosz Markowski .sta_mimo_ps_mode_cmdid = WMI_10X_STA_MIMO_PS_MODE_CMDID, 199b7e3adf9SBartosz Markowski .pdev_dfs_enable_cmdid = WMI_10X_PDEV_DFS_ENABLE_CMDID, 200b7e3adf9SBartosz Markowski .pdev_dfs_disable_cmdid = WMI_10X_PDEV_DFS_DISABLE_CMDID, 201b7e3adf9SBartosz Markowski .roam_scan_mode = WMI_10X_ROAM_SCAN_MODE, 202b7e3adf9SBartosz Markowski .roam_scan_rssi_threshold = WMI_10X_ROAM_SCAN_RSSI_THRESHOLD, 203b7e3adf9SBartosz Markowski .roam_scan_period = WMI_10X_ROAM_SCAN_PERIOD, 204b7e3adf9SBartosz Markowski .roam_scan_rssi_change_threshold = 205b7e3adf9SBartosz Markowski WMI_10X_ROAM_SCAN_RSSI_CHANGE_THRESHOLD, 206b7e3adf9SBartosz Markowski .roam_ap_profile = WMI_10X_ROAM_AP_PROFILE, 207b7e3adf9SBartosz Markowski .ofl_scan_add_ap_profile = WMI_10X_OFL_SCAN_ADD_AP_PROFILE, 208b7e3adf9SBartosz Markowski .ofl_scan_remove_ap_profile = WMI_10X_OFL_SCAN_REMOVE_AP_PROFILE, 209b7e3adf9SBartosz Markowski .ofl_scan_period = WMI_10X_OFL_SCAN_PERIOD, 210b7e3adf9SBartosz Markowski .p2p_dev_set_device_info = WMI_10X_P2P_DEV_SET_DEVICE_INFO, 211b7e3adf9SBartosz Markowski .p2p_dev_set_discoverability = WMI_10X_P2P_DEV_SET_DISCOVERABILITY, 212b7e3adf9SBartosz Markowski .p2p_go_set_beacon_ie = WMI_10X_P2P_GO_SET_BEACON_IE, 213b7e3adf9SBartosz Markowski .p2p_go_set_probe_resp_ie = WMI_10X_P2P_GO_SET_PROBE_RESP_IE, 21434957b25SBartosz Markowski .p2p_set_vendor_ie_data_cmdid = WMI_CMD_UNSUPPORTED, 21534957b25SBartosz Markowski .ap_ps_peer_param_cmdid = WMI_CMD_UNSUPPORTED, 21634957b25SBartosz Markowski .ap_ps_peer_uapsd_coex_cmdid = WMI_CMD_UNSUPPORTED, 217b7e3adf9SBartosz Markowski .peer_rate_retry_sched_cmdid = WMI_10X_PEER_RATE_RETRY_SCHED_CMDID, 218b7e3adf9SBartosz Markowski .wlan_profile_trigger_cmdid = WMI_10X_WLAN_PROFILE_TRIGGER_CMDID, 219b7e3adf9SBartosz Markowski .wlan_profile_set_hist_intvl_cmdid = 220b7e3adf9SBartosz Markowski WMI_10X_WLAN_PROFILE_SET_HIST_INTVL_CMDID, 221b7e3adf9SBartosz Markowski .wlan_profile_get_profile_data_cmdid = 222b7e3adf9SBartosz Markowski WMI_10X_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, 223b7e3adf9SBartosz Markowski .wlan_profile_enable_profile_id_cmdid = 224b7e3adf9SBartosz Markowski WMI_10X_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, 225b7e3adf9SBartosz Markowski .wlan_profile_list_profile_id_cmdid = 226b7e3adf9SBartosz Markowski WMI_10X_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, 227b7e3adf9SBartosz Markowski .pdev_suspend_cmdid = WMI_10X_PDEV_SUSPEND_CMDID, 228b7e3adf9SBartosz Markowski .pdev_resume_cmdid = WMI_10X_PDEV_RESUME_CMDID, 229b7e3adf9SBartosz Markowski .add_bcn_filter_cmdid = WMI_10X_ADD_BCN_FILTER_CMDID, 230b7e3adf9SBartosz Markowski .rmv_bcn_filter_cmdid = WMI_10X_RMV_BCN_FILTER_CMDID, 231b7e3adf9SBartosz Markowski .wow_add_wake_pattern_cmdid = WMI_10X_WOW_ADD_WAKE_PATTERN_CMDID, 232b7e3adf9SBartosz Markowski .wow_del_wake_pattern_cmdid = WMI_10X_WOW_DEL_WAKE_PATTERN_CMDID, 233b7e3adf9SBartosz Markowski .wow_enable_disable_wake_event_cmdid = 234b7e3adf9SBartosz Markowski WMI_10X_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, 235b7e3adf9SBartosz Markowski .wow_enable_cmdid = WMI_10X_WOW_ENABLE_CMDID, 236b7e3adf9SBartosz Markowski .wow_hostwakeup_from_sleep_cmdid = 237b7e3adf9SBartosz Markowski WMI_10X_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, 238b7e3adf9SBartosz Markowski .rtt_measreq_cmdid = WMI_10X_RTT_MEASREQ_CMDID, 239b7e3adf9SBartosz Markowski .rtt_tsf_cmdid = WMI_10X_RTT_TSF_CMDID, 240b7e3adf9SBartosz Markowski .vdev_spectral_scan_configure_cmdid = 241b7e3adf9SBartosz Markowski WMI_10X_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID, 242b7e3adf9SBartosz Markowski .vdev_spectral_scan_enable_cmdid = 243b7e3adf9SBartosz Markowski WMI_10X_VDEV_SPECTRAL_SCAN_ENABLE_CMDID, 244b7e3adf9SBartosz Markowski .request_stats_cmdid = WMI_10X_REQUEST_STATS_CMDID, 24534957b25SBartosz Markowski .set_arp_ns_offload_cmdid = WMI_CMD_UNSUPPORTED, 24634957b25SBartosz Markowski .network_list_offload_config_cmdid = WMI_CMD_UNSUPPORTED, 24734957b25SBartosz Markowski .gtk_offload_cmdid = WMI_CMD_UNSUPPORTED, 24834957b25SBartosz Markowski .csa_offload_enable_cmdid = WMI_CMD_UNSUPPORTED, 24934957b25SBartosz Markowski .csa_offload_chanswitch_cmdid = WMI_CMD_UNSUPPORTED, 25034957b25SBartosz Markowski .chatter_set_mode_cmdid = WMI_CMD_UNSUPPORTED, 25134957b25SBartosz Markowski .peer_tid_addba_cmdid = WMI_CMD_UNSUPPORTED, 25234957b25SBartosz Markowski .peer_tid_delba_cmdid = WMI_CMD_UNSUPPORTED, 25334957b25SBartosz Markowski .sta_dtim_ps_method_cmdid = WMI_CMD_UNSUPPORTED, 25434957b25SBartosz Markowski .sta_uapsd_auto_trig_cmdid = WMI_CMD_UNSUPPORTED, 25534957b25SBartosz Markowski .sta_keepalive_cmd = WMI_CMD_UNSUPPORTED, 256b7e3adf9SBartosz Markowski .echo_cmdid = WMI_10X_ECHO_CMDID, 257b7e3adf9SBartosz Markowski .pdev_utf_cmdid = WMI_10X_PDEV_UTF_CMDID, 258b7e3adf9SBartosz Markowski .dbglog_cfg_cmdid = WMI_10X_DBGLOG_CFG_CMDID, 259b7e3adf9SBartosz Markowski .pdev_qvit_cmdid = WMI_10X_PDEV_QVIT_CMDID, 26034957b25SBartosz Markowski .pdev_ftm_intg_cmdid = WMI_CMD_UNSUPPORTED, 26134957b25SBartosz Markowski .vdev_set_keepalive_cmdid = WMI_CMD_UNSUPPORTED, 26234957b25SBartosz Markowski .vdev_get_keepalive_cmdid = WMI_CMD_UNSUPPORTED, 26334957b25SBartosz Markowski .force_fw_hang_cmdid = WMI_CMD_UNSUPPORTED, 264b7e3adf9SBartosz Markowski .gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID, 265b7e3adf9SBartosz Markowski .gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID, 266b7e3adf9SBartosz Markowski }; 267ce42870eSBartosz Markowski 2686d1506e7SBartosz Markowski /* MAIN WMI VDEV param map */ 2696d1506e7SBartosz Markowski static struct wmi_vdev_param_map wmi_vdev_param_map = { 2706d1506e7SBartosz Markowski .rts_threshold = WMI_VDEV_PARAM_RTS_THRESHOLD, 2716d1506e7SBartosz Markowski .fragmentation_threshold = WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD, 2726d1506e7SBartosz Markowski .beacon_interval = WMI_VDEV_PARAM_BEACON_INTERVAL, 2736d1506e7SBartosz Markowski .listen_interval = WMI_VDEV_PARAM_LISTEN_INTERVAL, 2746d1506e7SBartosz Markowski .multicast_rate = WMI_VDEV_PARAM_MULTICAST_RATE, 2756d1506e7SBartosz Markowski .mgmt_tx_rate = WMI_VDEV_PARAM_MGMT_TX_RATE, 2766d1506e7SBartosz Markowski .slot_time = WMI_VDEV_PARAM_SLOT_TIME, 2776d1506e7SBartosz Markowski .preamble = WMI_VDEV_PARAM_PREAMBLE, 2786d1506e7SBartosz Markowski .swba_time = WMI_VDEV_PARAM_SWBA_TIME, 2796d1506e7SBartosz Markowski .wmi_vdev_stats_update_period = WMI_VDEV_STATS_UPDATE_PERIOD, 2806d1506e7SBartosz Markowski .wmi_vdev_pwrsave_ageout_time = WMI_VDEV_PWRSAVE_AGEOUT_TIME, 2816d1506e7SBartosz Markowski .wmi_vdev_host_swba_interval = WMI_VDEV_HOST_SWBA_INTERVAL, 2826d1506e7SBartosz Markowski .dtim_period = WMI_VDEV_PARAM_DTIM_PERIOD, 2836d1506e7SBartosz Markowski .wmi_vdev_oc_scheduler_air_time_limit = 2846d1506e7SBartosz Markowski WMI_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, 2856d1506e7SBartosz Markowski .wds = WMI_VDEV_PARAM_WDS, 2866d1506e7SBartosz Markowski .atim_window = WMI_VDEV_PARAM_ATIM_WINDOW, 2876d1506e7SBartosz Markowski .bmiss_count_max = WMI_VDEV_PARAM_BMISS_COUNT_MAX, 2886d1506e7SBartosz Markowski .bmiss_first_bcnt = WMI_VDEV_PARAM_BMISS_FIRST_BCNT, 2896d1506e7SBartosz Markowski .bmiss_final_bcnt = WMI_VDEV_PARAM_BMISS_FINAL_BCNT, 2906d1506e7SBartosz Markowski .feature_wmm = WMI_VDEV_PARAM_FEATURE_WMM, 2916d1506e7SBartosz Markowski .chwidth = WMI_VDEV_PARAM_CHWIDTH, 2926d1506e7SBartosz Markowski .chextoffset = WMI_VDEV_PARAM_CHEXTOFFSET, 2936d1506e7SBartosz Markowski .disable_htprotection = WMI_VDEV_PARAM_DISABLE_HTPROTECTION, 2946d1506e7SBartosz Markowski .sta_quickkickout = WMI_VDEV_PARAM_STA_QUICKKICKOUT, 2956d1506e7SBartosz Markowski .mgmt_rate = WMI_VDEV_PARAM_MGMT_RATE, 2966d1506e7SBartosz Markowski .protection_mode = WMI_VDEV_PARAM_PROTECTION_MODE, 2976d1506e7SBartosz Markowski .fixed_rate = WMI_VDEV_PARAM_FIXED_RATE, 2986d1506e7SBartosz Markowski .sgi = WMI_VDEV_PARAM_SGI, 2996d1506e7SBartosz Markowski .ldpc = WMI_VDEV_PARAM_LDPC, 3006d1506e7SBartosz Markowski .tx_stbc = WMI_VDEV_PARAM_TX_STBC, 3016d1506e7SBartosz Markowski .rx_stbc = WMI_VDEV_PARAM_RX_STBC, 3026d1506e7SBartosz Markowski .intra_bss_fwd = WMI_VDEV_PARAM_INTRA_BSS_FWD, 3036d1506e7SBartosz Markowski .def_keyid = WMI_VDEV_PARAM_DEF_KEYID, 3046d1506e7SBartosz Markowski .nss = WMI_VDEV_PARAM_NSS, 3056d1506e7SBartosz Markowski .bcast_data_rate = WMI_VDEV_PARAM_BCAST_DATA_RATE, 3066d1506e7SBartosz Markowski .mcast_data_rate = WMI_VDEV_PARAM_MCAST_DATA_RATE, 3076d1506e7SBartosz Markowski .mcast_indicate = WMI_VDEV_PARAM_MCAST_INDICATE, 3086d1506e7SBartosz Markowski .dhcp_indicate = WMI_VDEV_PARAM_DHCP_INDICATE, 3096d1506e7SBartosz Markowski .unknown_dest_indicate = WMI_VDEV_PARAM_UNKNOWN_DEST_INDICATE, 3106d1506e7SBartosz Markowski .ap_keepalive_min_idle_inactive_time_secs = 3116d1506e7SBartosz Markowski WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, 3126d1506e7SBartosz Markowski .ap_keepalive_max_idle_inactive_time_secs = 3136d1506e7SBartosz Markowski WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, 3146d1506e7SBartosz Markowski .ap_keepalive_max_unresponsive_time_secs = 3156d1506e7SBartosz Markowski WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, 3166d1506e7SBartosz Markowski .ap_enable_nawds = WMI_VDEV_PARAM_AP_ENABLE_NAWDS, 3176d1506e7SBartosz Markowski .mcast2ucast_set = WMI_VDEV_PARAM_UNSUPPORTED, 3186d1506e7SBartosz Markowski .enable_rtscts = WMI_VDEV_PARAM_ENABLE_RTSCTS, 3196d1506e7SBartosz Markowski .txbf = WMI_VDEV_PARAM_TXBF, 3206d1506e7SBartosz Markowski .packet_powersave = WMI_VDEV_PARAM_PACKET_POWERSAVE, 3216d1506e7SBartosz Markowski .drop_unencry = WMI_VDEV_PARAM_DROP_UNENCRY, 3226d1506e7SBartosz Markowski .tx_encap_type = WMI_VDEV_PARAM_TX_ENCAP_TYPE, 3236d1506e7SBartosz Markowski .ap_detect_out_of_sync_sleeping_sta_time_secs = 3246d1506e7SBartosz Markowski WMI_VDEV_PARAM_UNSUPPORTED, 3256d1506e7SBartosz Markowski }; 3266d1506e7SBartosz Markowski 3276d1506e7SBartosz Markowski /* 10.X WMI VDEV param map */ 3286d1506e7SBartosz Markowski static struct wmi_vdev_param_map wmi_10x_vdev_param_map = { 3296d1506e7SBartosz Markowski .rts_threshold = WMI_10X_VDEV_PARAM_RTS_THRESHOLD, 3306d1506e7SBartosz Markowski .fragmentation_threshold = WMI_10X_VDEV_PARAM_FRAGMENTATION_THRESHOLD, 3316d1506e7SBartosz Markowski .beacon_interval = WMI_10X_VDEV_PARAM_BEACON_INTERVAL, 3326d1506e7SBartosz Markowski .listen_interval = WMI_10X_VDEV_PARAM_LISTEN_INTERVAL, 3336d1506e7SBartosz Markowski .multicast_rate = WMI_10X_VDEV_PARAM_MULTICAST_RATE, 3346d1506e7SBartosz Markowski .mgmt_tx_rate = WMI_10X_VDEV_PARAM_MGMT_TX_RATE, 3356d1506e7SBartosz Markowski .slot_time = WMI_10X_VDEV_PARAM_SLOT_TIME, 3366d1506e7SBartosz Markowski .preamble = WMI_10X_VDEV_PARAM_PREAMBLE, 3376d1506e7SBartosz Markowski .swba_time = WMI_10X_VDEV_PARAM_SWBA_TIME, 3386d1506e7SBartosz Markowski .wmi_vdev_stats_update_period = WMI_10X_VDEV_STATS_UPDATE_PERIOD, 3396d1506e7SBartosz Markowski .wmi_vdev_pwrsave_ageout_time = WMI_10X_VDEV_PWRSAVE_AGEOUT_TIME, 3406d1506e7SBartosz Markowski .wmi_vdev_host_swba_interval = WMI_10X_VDEV_HOST_SWBA_INTERVAL, 3416d1506e7SBartosz Markowski .dtim_period = WMI_10X_VDEV_PARAM_DTIM_PERIOD, 3426d1506e7SBartosz Markowski .wmi_vdev_oc_scheduler_air_time_limit = 3436d1506e7SBartosz Markowski WMI_10X_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, 3446d1506e7SBartosz Markowski .wds = WMI_10X_VDEV_PARAM_WDS, 3456d1506e7SBartosz Markowski .atim_window = WMI_10X_VDEV_PARAM_ATIM_WINDOW, 3466d1506e7SBartosz Markowski .bmiss_count_max = WMI_10X_VDEV_PARAM_BMISS_COUNT_MAX, 3476d1506e7SBartosz Markowski .bmiss_first_bcnt = WMI_VDEV_PARAM_UNSUPPORTED, 3486d1506e7SBartosz Markowski .bmiss_final_bcnt = WMI_VDEV_PARAM_UNSUPPORTED, 3496d1506e7SBartosz Markowski .feature_wmm = WMI_10X_VDEV_PARAM_FEATURE_WMM, 3506d1506e7SBartosz Markowski .chwidth = WMI_10X_VDEV_PARAM_CHWIDTH, 3516d1506e7SBartosz Markowski .chextoffset = WMI_10X_VDEV_PARAM_CHEXTOFFSET, 3526d1506e7SBartosz Markowski .disable_htprotection = WMI_10X_VDEV_PARAM_DISABLE_HTPROTECTION, 3536d1506e7SBartosz Markowski .sta_quickkickout = WMI_10X_VDEV_PARAM_STA_QUICKKICKOUT, 3546d1506e7SBartosz Markowski .mgmt_rate = WMI_10X_VDEV_PARAM_MGMT_RATE, 3556d1506e7SBartosz Markowski .protection_mode = WMI_10X_VDEV_PARAM_PROTECTION_MODE, 3566d1506e7SBartosz Markowski .fixed_rate = WMI_10X_VDEV_PARAM_FIXED_RATE, 3576d1506e7SBartosz Markowski .sgi = WMI_10X_VDEV_PARAM_SGI, 3586d1506e7SBartosz Markowski .ldpc = WMI_10X_VDEV_PARAM_LDPC, 3596d1506e7SBartosz Markowski .tx_stbc = WMI_10X_VDEV_PARAM_TX_STBC, 3606d1506e7SBartosz Markowski .rx_stbc = WMI_10X_VDEV_PARAM_RX_STBC, 3616d1506e7SBartosz Markowski .intra_bss_fwd = WMI_10X_VDEV_PARAM_INTRA_BSS_FWD, 3626d1506e7SBartosz Markowski .def_keyid = WMI_10X_VDEV_PARAM_DEF_KEYID, 3636d1506e7SBartosz Markowski .nss = WMI_10X_VDEV_PARAM_NSS, 3646d1506e7SBartosz Markowski .bcast_data_rate = WMI_10X_VDEV_PARAM_BCAST_DATA_RATE, 3656d1506e7SBartosz Markowski .mcast_data_rate = WMI_10X_VDEV_PARAM_MCAST_DATA_RATE, 3666d1506e7SBartosz Markowski .mcast_indicate = WMI_10X_VDEV_PARAM_MCAST_INDICATE, 3676d1506e7SBartosz Markowski .dhcp_indicate = WMI_10X_VDEV_PARAM_DHCP_INDICATE, 3686d1506e7SBartosz Markowski .unknown_dest_indicate = WMI_10X_VDEV_PARAM_UNKNOWN_DEST_INDICATE, 3696d1506e7SBartosz Markowski .ap_keepalive_min_idle_inactive_time_secs = 3706d1506e7SBartosz Markowski WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, 3716d1506e7SBartosz Markowski .ap_keepalive_max_idle_inactive_time_secs = 3726d1506e7SBartosz Markowski WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, 3736d1506e7SBartosz Markowski .ap_keepalive_max_unresponsive_time_secs = 3746d1506e7SBartosz Markowski WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, 3756d1506e7SBartosz Markowski .ap_enable_nawds = WMI_10X_VDEV_PARAM_AP_ENABLE_NAWDS, 3766d1506e7SBartosz Markowski .mcast2ucast_set = WMI_10X_VDEV_PARAM_MCAST2UCAST_SET, 3776d1506e7SBartosz Markowski .enable_rtscts = WMI_10X_VDEV_PARAM_ENABLE_RTSCTS, 3786d1506e7SBartosz Markowski .txbf = WMI_VDEV_PARAM_UNSUPPORTED, 3796d1506e7SBartosz Markowski .packet_powersave = WMI_VDEV_PARAM_UNSUPPORTED, 3806d1506e7SBartosz Markowski .drop_unencry = WMI_VDEV_PARAM_UNSUPPORTED, 3816d1506e7SBartosz Markowski .tx_encap_type = WMI_VDEV_PARAM_UNSUPPORTED, 3826d1506e7SBartosz Markowski .ap_detect_out_of_sync_sleeping_sta_time_secs = 3836d1506e7SBartosz Markowski WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS, 3846d1506e7SBartosz Markowski }; 3856d1506e7SBartosz Markowski 386226a339bSBartosz Markowski static struct wmi_pdev_param_map wmi_pdev_param_map = { 387226a339bSBartosz Markowski .tx_chain_mask = WMI_PDEV_PARAM_TX_CHAIN_MASK, 388226a339bSBartosz Markowski .rx_chain_mask = WMI_PDEV_PARAM_RX_CHAIN_MASK, 389226a339bSBartosz Markowski .txpower_limit2g = WMI_PDEV_PARAM_TXPOWER_LIMIT2G, 390226a339bSBartosz Markowski .txpower_limit5g = WMI_PDEV_PARAM_TXPOWER_LIMIT5G, 391226a339bSBartosz Markowski .txpower_scale = WMI_PDEV_PARAM_TXPOWER_SCALE, 392226a339bSBartosz Markowski .beacon_gen_mode = WMI_PDEV_PARAM_BEACON_GEN_MODE, 393226a339bSBartosz Markowski .beacon_tx_mode = WMI_PDEV_PARAM_BEACON_TX_MODE, 394226a339bSBartosz Markowski .resmgr_offchan_mode = WMI_PDEV_PARAM_RESMGR_OFFCHAN_MODE, 395226a339bSBartosz Markowski .protection_mode = WMI_PDEV_PARAM_PROTECTION_MODE, 396226a339bSBartosz Markowski .dynamic_bw = WMI_PDEV_PARAM_DYNAMIC_BW, 397226a339bSBartosz Markowski .non_agg_sw_retry_th = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH, 398226a339bSBartosz Markowski .agg_sw_retry_th = WMI_PDEV_PARAM_AGG_SW_RETRY_TH, 399226a339bSBartosz Markowski .sta_kickout_th = WMI_PDEV_PARAM_STA_KICKOUT_TH, 400226a339bSBartosz Markowski .ac_aggrsize_scaling = WMI_PDEV_PARAM_AC_AGGRSIZE_SCALING, 401226a339bSBartosz Markowski .ltr_enable = WMI_PDEV_PARAM_LTR_ENABLE, 402226a339bSBartosz Markowski .ltr_ac_latency_be = WMI_PDEV_PARAM_LTR_AC_LATENCY_BE, 403226a339bSBartosz Markowski .ltr_ac_latency_bk = WMI_PDEV_PARAM_LTR_AC_LATENCY_BK, 404226a339bSBartosz Markowski .ltr_ac_latency_vi = WMI_PDEV_PARAM_LTR_AC_LATENCY_VI, 405226a339bSBartosz Markowski .ltr_ac_latency_vo = WMI_PDEV_PARAM_LTR_AC_LATENCY_VO, 406226a339bSBartosz Markowski .ltr_ac_latency_timeout = WMI_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT, 407226a339bSBartosz Markowski .ltr_sleep_override = WMI_PDEV_PARAM_LTR_SLEEP_OVERRIDE, 408226a339bSBartosz Markowski .ltr_rx_override = WMI_PDEV_PARAM_LTR_RX_OVERRIDE, 409226a339bSBartosz Markowski .ltr_tx_activity_timeout = WMI_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT, 410226a339bSBartosz Markowski .l1ss_enable = WMI_PDEV_PARAM_L1SS_ENABLE, 411226a339bSBartosz Markowski .dsleep_enable = WMI_PDEV_PARAM_DSLEEP_ENABLE, 412226a339bSBartosz Markowski .pcielp_txbuf_flush = WMI_PDEV_PARAM_PCIELP_TXBUF_FLUSH, 413226a339bSBartosz Markowski .pcielp_txbuf_watermark = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_EN, 414226a339bSBartosz Markowski .pcielp_txbuf_tmo_en = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_EN, 415226a339bSBartosz Markowski .pcielp_txbuf_tmo_value = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE, 416226a339bSBartosz Markowski .pdev_stats_update_period = WMI_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD, 417226a339bSBartosz Markowski .vdev_stats_update_period = WMI_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD, 418226a339bSBartosz Markowski .peer_stats_update_period = WMI_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD, 419226a339bSBartosz Markowski .bcnflt_stats_update_period = WMI_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, 420226a339bSBartosz Markowski .pmf_qos = WMI_PDEV_PARAM_PMF_QOS, 421226a339bSBartosz Markowski .arp_ac_override = WMI_PDEV_PARAM_ARP_AC_OVERRIDE, 422226a339bSBartosz Markowski .arpdhcp_ac_override = WMI_PDEV_PARAM_UNSUPPORTED, 423226a339bSBartosz Markowski .dcs = WMI_PDEV_PARAM_DCS, 424226a339bSBartosz Markowski .ani_enable = WMI_PDEV_PARAM_ANI_ENABLE, 425226a339bSBartosz Markowski .ani_poll_period = WMI_PDEV_PARAM_ANI_POLL_PERIOD, 426226a339bSBartosz Markowski .ani_listen_period = WMI_PDEV_PARAM_ANI_LISTEN_PERIOD, 427226a339bSBartosz Markowski .ani_ofdm_level = WMI_PDEV_PARAM_ANI_OFDM_LEVEL, 428226a339bSBartosz Markowski .ani_cck_level = WMI_PDEV_PARAM_ANI_CCK_LEVEL, 429226a339bSBartosz Markowski .dyntxchain = WMI_PDEV_PARAM_DYNTXCHAIN, 430226a339bSBartosz Markowski .proxy_sta = WMI_PDEV_PARAM_PROXY_STA, 431226a339bSBartosz Markowski .idle_ps_config = WMI_PDEV_PARAM_IDLE_PS_CONFIG, 432226a339bSBartosz Markowski .power_gating_sleep = WMI_PDEV_PARAM_POWER_GATING_SLEEP, 433226a339bSBartosz Markowski .fast_channel_reset = WMI_PDEV_PARAM_UNSUPPORTED, 434226a339bSBartosz Markowski .burst_dur = WMI_PDEV_PARAM_UNSUPPORTED, 435226a339bSBartosz Markowski .burst_enable = WMI_PDEV_PARAM_UNSUPPORTED, 436226a339bSBartosz Markowski }; 437226a339bSBartosz Markowski 438226a339bSBartosz Markowski static struct wmi_pdev_param_map wmi_10x_pdev_param_map = { 439226a339bSBartosz Markowski .tx_chain_mask = WMI_10X_PDEV_PARAM_TX_CHAIN_MASK, 440226a339bSBartosz Markowski .rx_chain_mask = WMI_10X_PDEV_PARAM_RX_CHAIN_MASK, 441226a339bSBartosz Markowski .txpower_limit2g = WMI_10X_PDEV_PARAM_TXPOWER_LIMIT2G, 442226a339bSBartosz Markowski .txpower_limit5g = WMI_10X_PDEV_PARAM_TXPOWER_LIMIT5G, 443226a339bSBartosz Markowski .txpower_scale = WMI_10X_PDEV_PARAM_TXPOWER_SCALE, 444226a339bSBartosz Markowski .beacon_gen_mode = WMI_10X_PDEV_PARAM_BEACON_GEN_MODE, 445226a339bSBartosz Markowski .beacon_tx_mode = WMI_10X_PDEV_PARAM_BEACON_TX_MODE, 446226a339bSBartosz Markowski .resmgr_offchan_mode = WMI_10X_PDEV_PARAM_RESMGR_OFFCHAN_MODE, 447226a339bSBartosz Markowski .protection_mode = WMI_10X_PDEV_PARAM_PROTECTION_MODE, 448226a339bSBartosz Markowski .dynamic_bw = WMI_10X_PDEV_PARAM_DYNAMIC_BW, 449226a339bSBartosz Markowski .non_agg_sw_retry_th = WMI_10X_PDEV_PARAM_NON_AGG_SW_RETRY_TH, 450226a339bSBartosz Markowski .agg_sw_retry_th = WMI_10X_PDEV_PARAM_AGG_SW_RETRY_TH, 451226a339bSBartosz Markowski .sta_kickout_th = WMI_10X_PDEV_PARAM_STA_KICKOUT_TH, 452226a339bSBartosz Markowski .ac_aggrsize_scaling = WMI_10X_PDEV_PARAM_AC_AGGRSIZE_SCALING, 453226a339bSBartosz Markowski .ltr_enable = WMI_10X_PDEV_PARAM_LTR_ENABLE, 454226a339bSBartosz Markowski .ltr_ac_latency_be = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BE, 455226a339bSBartosz Markowski .ltr_ac_latency_bk = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BK, 456226a339bSBartosz Markowski .ltr_ac_latency_vi = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VI, 457226a339bSBartosz Markowski .ltr_ac_latency_vo = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VO, 458226a339bSBartosz Markowski .ltr_ac_latency_timeout = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT, 459226a339bSBartosz Markowski .ltr_sleep_override = WMI_10X_PDEV_PARAM_LTR_SLEEP_OVERRIDE, 460226a339bSBartosz Markowski .ltr_rx_override = WMI_10X_PDEV_PARAM_LTR_RX_OVERRIDE, 461226a339bSBartosz Markowski .ltr_tx_activity_timeout = WMI_10X_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT, 462226a339bSBartosz Markowski .l1ss_enable = WMI_10X_PDEV_PARAM_L1SS_ENABLE, 463226a339bSBartosz Markowski .dsleep_enable = WMI_10X_PDEV_PARAM_DSLEEP_ENABLE, 464226a339bSBartosz Markowski .pcielp_txbuf_flush = WMI_PDEV_PARAM_UNSUPPORTED, 465226a339bSBartosz Markowski .pcielp_txbuf_watermark = WMI_PDEV_PARAM_UNSUPPORTED, 466226a339bSBartosz Markowski .pcielp_txbuf_tmo_en = WMI_PDEV_PARAM_UNSUPPORTED, 467226a339bSBartosz Markowski .pcielp_txbuf_tmo_value = WMI_PDEV_PARAM_UNSUPPORTED, 468226a339bSBartosz Markowski .pdev_stats_update_period = WMI_10X_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD, 469226a339bSBartosz Markowski .vdev_stats_update_period = WMI_10X_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD, 470226a339bSBartosz Markowski .peer_stats_update_period = WMI_10X_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD, 471226a339bSBartosz Markowski .bcnflt_stats_update_period = 472226a339bSBartosz Markowski WMI_10X_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, 473226a339bSBartosz Markowski .pmf_qos = WMI_10X_PDEV_PARAM_PMF_QOS, 474226a339bSBartosz Markowski .arp_ac_override = WMI_PDEV_PARAM_UNSUPPORTED, 475226a339bSBartosz Markowski .arpdhcp_ac_override = WMI_10X_PDEV_PARAM_ARPDHCP_AC_OVERRIDE, 476226a339bSBartosz Markowski .dcs = WMI_10X_PDEV_PARAM_DCS, 477226a339bSBartosz Markowski .ani_enable = WMI_10X_PDEV_PARAM_ANI_ENABLE, 478226a339bSBartosz Markowski .ani_poll_period = WMI_10X_PDEV_PARAM_ANI_POLL_PERIOD, 479226a339bSBartosz Markowski .ani_listen_period = WMI_10X_PDEV_PARAM_ANI_LISTEN_PERIOD, 480226a339bSBartosz Markowski .ani_ofdm_level = WMI_10X_PDEV_PARAM_ANI_OFDM_LEVEL, 481226a339bSBartosz Markowski .ani_cck_level = WMI_10X_PDEV_PARAM_ANI_CCK_LEVEL, 482226a339bSBartosz Markowski .dyntxchain = WMI_10X_PDEV_PARAM_DYNTXCHAIN, 483226a339bSBartosz Markowski .proxy_sta = WMI_PDEV_PARAM_UNSUPPORTED, 484226a339bSBartosz Markowski .idle_ps_config = WMI_PDEV_PARAM_UNSUPPORTED, 485226a339bSBartosz Markowski .power_gating_sleep = WMI_PDEV_PARAM_UNSUPPORTED, 486226a339bSBartosz Markowski .fast_channel_reset = WMI_10X_PDEV_PARAM_FAST_CHANNEL_RESET, 487226a339bSBartosz Markowski .burst_dur = WMI_10X_PDEV_PARAM_BURST_DUR, 488226a339bSBartosz Markowski .burst_enable = WMI_10X_PDEV_PARAM_BURST_ENABLE, 489226a339bSBartosz Markowski }; 490226a339bSBartosz Markowski 4915e3dd157SKalle Valo int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) 4925e3dd157SKalle Valo { 4935e3dd157SKalle Valo int ret; 4945e3dd157SKalle Valo ret = wait_for_completion_timeout(&ar->wmi.service_ready, 4955e3dd157SKalle Valo WMI_SERVICE_READY_TIMEOUT_HZ); 4965e3dd157SKalle Valo return ret; 4975e3dd157SKalle Valo } 4985e3dd157SKalle Valo 4995e3dd157SKalle Valo int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar) 5005e3dd157SKalle Valo { 5015e3dd157SKalle Valo int ret; 5025e3dd157SKalle Valo ret = wait_for_completion_timeout(&ar->wmi.unified_ready, 5035e3dd157SKalle Valo WMI_UNIFIED_READY_TIMEOUT_HZ); 5045e3dd157SKalle Valo return ret; 5055e3dd157SKalle Valo } 5065e3dd157SKalle Valo 5075e3dd157SKalle Valo static struct sk_buff *ath10k_wmi_alloc_skb(u32 len) 5085e3dd157SKalle Valo { 5095e3dd157SKalle Valo struct sk_buff *skb; 5105e3dd157SKalle Valo u32 round_len = roundup(len, 4); 5115e3dd157SKalle Valo 5125e3dd157SKalle Valo skb = ath10k_htc_alloc_skb(WMI_SKB_HEADROOM + round_len); 5135e3dd157SKalle Valo if (!skb) 5145e3dd157SKalle Valo return NULL; 5155e3dd157SKalle Valo 5165e3dd157SKalle Valo skb_reserve(skb, WMI_SKB_HEADROOM); 5175e3dd157SKalle Valo if (!IS_ALIGNED((unsigned long)skb->data, 4)) 5185e3dd157SKalle Valo ath10k_warn("Unaligned WMI skb\n"); 5195e3dd157SKalle Valo 5205e3dd157SKalle Valo skb_put(skb, round_len); 5215e3dd157SKalle Valo memset(skb->data, 0, round_len); 5225e3dd157SKalle Valo 5235e3dd157SKalle Valo return skb; 5245e3dd157SKalle Valo } 5255e3dd157SKalle Valo 5265e3dd157SKalle Valo static void ath10k_wmi_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) 5275e3dd157SKalle Valo { 5285e3dd157SKalle Valo dev_kfree_skb(skb); 5295e3dd157SKalle Valo } 5305e3dd157SKalle Valo 531be8b3943SMichal Kazior static int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb, 532ce42870eSBartosz Markowski u32 cmd_id) 5335e3dd157SKalle Valo { 5345e3dd157SKalle Valo struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); 5355e3dd157SKalle Valo struct wmi_cmd_hdr *cmd_hdr; 536be8b3943SMichal Kazior int ret; 5375e3dd157SKalle Valo u32 cmd = 0; 5385e3dd157SKalle Valo 5395e3dd157SKalle Valo if (skb_push(skb, sizeof(struct wmi_cmd_hdr)) == NULL) 5405e3dd157SKalle Valo return -ENOMEM; 5415e3dd157SKalle Valo 5425e3dd157SKalle Valo cmd |= SM(cmd_id, WMI_CMD_HDR_CMD_ID); 5435e3dd157SKalle Valo 5445e3dd157SKalle Valo cmd_hdr = (struct wmi_cmd_hdr *)skb->data; 5455e3dd157SKalle Valo cmd_hdr->cmd_id = __cpu_to_le32(cmd); 5465e3dd157SKalle Valo 5475e3dd157SKalle Valo memset(skb_cb, 0, sizeof(*skb_cb)); 548be8b3943SMichal Kazior ret = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb); 549be8b3943SMichal Kazior trace_ath10k_wmi_cmd(cmd_id, skb->data, skb->len, ret); 5505e3dd157SKalle Valo 551be8b3943SMichal Kazior if (ret) 552be8b3943SMichal Kazior goto err_pull; 5535e3dd157SKalle Valo 5545e3dd157SKalle Valo return 0; 555be8b3943SMichal Kazior 556be8b3943SMichal Kazior err_pull: 557be8b3943SMichal Kazior skb_pull(skb, sizeof(struct wmi_cmd_hdr)); 558be8b3943SMichal Kazior return ret; 559be8b3943SMichal Kazior } 560be8b3943SMichal Kazior 561ed54388aSMichal Kazior static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif) 562ed54388aSMichal Kazior { 563ed54388aSMichal Kazior struct wmi_bcn_tx_arg arg = {0}; 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 571ed54388aSMichal Kazior arg.vdev_id = arvif->vdev_id; 572ed54388aSMichal Kazior arg.tx_rate = 0; 573ed54388aSMichal Kazior arg.tx_power = 0; 574ed54388aSMichal Kazior arg.bcn = arvif->beacon->data; 575ed54388aSMichal Kazior arg.bcn_len = arvif->beacon->len; 576ed54388aSMichal Kazior 577ed54388aSMichal Kazior ret = ath10k_wmi_beacon_send_nowait(arvif->ar, &arg); 578ed54388aSMichal Kazior if (ret) 579ed54388aSMichal Kazior return; 580ed54388aSMichal Kazior 581ed54388aSMichal Kazior dev_kfree_skb_any(arvif->beacon); 582ed54388aSMichal Kazior arvif->beacon = NULL; 583ed54388aSMichal Kazior } 584ed54388aSMichal Kazior 585ed54388aSMichal Kazior static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac, 586ed54388aSMichal Kazior struct ieee80211_vif *vif) 587ed54388aSMichal Kazior { 588ed54388aSMichal Kazior struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); 589ed54388aSMichal Kazior 590ed54388aSMichal Kazior ath10k_wmi_tx_beacon_nowait(arvif); 591ed54388aSMichal Kazior } 592ed54388aSMichal Kazior 593ed54388aSMichal Kazior static void ath10k_wmi_tx_beacons_nowait(struct ath10k *ar) 594ed54388aSMichal Kazior { 595ed54388aSMichal Kazior spin_lock_bh(&ar->data_lock); 596ed54388aSMichal Kazior ieee80211_iterate_active_interfaces_atomic(ar->hw, 597ed54388aSMichal Kazior IEEE80211_IFACE_ITER_NORMAL, 598ed54388aSMichal Kazior ath10k_wmi_tx_beacons_iter, 599ed54388aSMichal Kazior NULL); 600ed54388aSMichal Kazior spin_unlock_bh(&ar->data_lock); 601ed54388aSMichal Kazior } 602ed54388aSMichal Kazior 60312acbc43SMichal Kazior static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar) 604be8b3943SMichal Kazior { 605ed54388aSMichal Kazior /* try to send pending beacons first. they take priority */ 606ed54388aSMichal Kazior ath10k_wmi_tx_beacons_nowait(ar); 607ed54388aSMichal Kazior 608be8b3943SMichal Kazior wake_up(&ar->wmi.tx_credits_wq); 609be8b3943SMichal Kazior } 610be8b3943SMichal Kazior 611be8b3943SMichal Kazior static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, 612ce42870eSBartosz Markowski u32 cmd_id) 613be8b3943SMichal Kazior { 61434957b25SBartosz Markowski int ret = -EOPNOTSUPP; 615be8b3943SMichal Kazior 61656b84287SKalle Valo might_sleep(); 61756b84287SKalle Valo 61834957b25SBartosz Markowski if (cmd_id == WMI_CMD_UNSUPPORTED) { 61955321559SBartosz Markowski ath10k_warn("wmi command %d is not supported by firmware\n", 62055321559SBartosz Markowski cmd_id); 62155321559SBartosz Markowski return ret; 62255321559SBartosz Markowski } 62355321559SBartosz Markowski 624be8b3943SMichal Kazior wait_event_timeout(ar->wmi.tx_credits_wq, ({ 625ed54388aSMichal Kazior /* try to send pending beacons first. they take priority */ 626ed54388aSMichal Kazior ath10k_wmi_tx_beacons_nowait(ar); 627ed54388aSMichal Kazior 628be8b3943SMichal Kazior ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id); 629be8b3943SMichal Kazior (ret != -EAGAIN); 630be8b3943SMichal Kazior }), 3*HZ); 631be8b3943SMichal Kazior 632be8b3943SMichal Kazior if (ret) 633be8b3943SMichal Kazior dev_kfree_skb_any(skb); 634be8b3943SMichal Kazior 635be8b3943SMichal Kazior return ret; 6365e3dd157SKalle Valo } 6375e3dd157SKalle Valo 6385e00d31aSBartosz Markowski int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb) 6395e00d31aSBartosz Markowski { 6405e00d31aSBartosz Markowski int ret = 0; 6415e00d31aSBartosz Markowski struct wmi_mgmt_tx_cmd *cmd; 6425e00d31aSBartosz Markowski struct ieee80211_hdr *hdr; 6435e00d31aSBartosz Markowski struct sk_buff *wmi_skb; 6445e00d31aSBartosz Markowski struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 6455e00d31aSBartosz Markowski int len; 6465e00d31aSBartosz Markowski u16 fc; 6475e00d31aSBartosz Markowski 6485e00d31aSBartosz Markowski hdr = (struct ieee80211_hdr *)skb->data; 6495e00d31aSBartosz Markowski fc = le16_to_cpu(hdr->frame_control); 6505e00d31aSBartosz Markowski 6515e00d31aSBartosz Markowski if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control))) 6525e00d31aSBartosz Markowski return -EINVAL; 6535e00d31aSBartosz Markowski 6545e00d31aSBartosz Markowski len = sizeof(cmd->hdr) + skb->len; 6555e00d31aSBartosz Markowski len = round_up(len, 4); 6565e00d31aSBartosz Markowski 6575e00d31aSBartosz Markowski wmi_skb = ath10k_wmi_alloc_skb(len); 6585e00d31aSBartosz Markowski if (!wmi_skb) 6595e00d31aSBartosz Markowski return -ENOMEM; 6605e00d31aSBartosz Markowski 6615e00d31aSBartosz Markowski cmd = (struct wmi_mgmt_tx_cmd *)wmi_skb->data; 6625e00d31aSBartosz Markowski 6635e00d31aSBartosz Markowski cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(skb)->vdev_id); 6645e00d31aSBartosz Markowski cmd->hdr.tx_rate = 0; 6655e00d31aSBartosz Markowski cmd->hdr.tx_power = 0; 6665e00d31aSBartosz Markowski cmd->hdr.buf_len = __cpu_to_le32((u32)(skb->len)); 6675e00d31aSBartosz Markowski 6685e00d31aSBartosz Markowski memcpy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr), ETH_ALEN); 6695e00d31aSBartosz Markowski memcpy(cmd->buf, skb->data, skb->len); 6705e00d31aSBartosz Markowski 6715e00d31aSBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n", 6725e00d31aSBartosz Markowski wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE, 6735e00d31aSBartosz Markowski fc & IEEE80211_FCTL_STYPE); 6745e00d31aSBartosz Markowski 6755e00d31aSBartosz Markowski /* Send the management frame buffer to the target */ 6765e00d31aSBartosz Markowski ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid); 6775fb5e41fSMichal Kazior if (ret) 6785e00d31aSBartosz Markowski return ret; 6795e00d31aSBartosz Markowski 6805e00d31aSBartosz Markowski /* TODO: report tx status to mac80211 - temporary just ACK */ 6815e00d31aSBartosz Markowski info->flags |= IEEE80211_TX_STAT_ACK; 6825e00d31aSBartosz Markowski ieee80211_tx_status_irqsafe(ar->hw, skb); 6835e00d31aSBartosz Markowski 6845e00d31aSBartosz Markowski return ret; 6855e00d31aSBartosz Markowski } 6865e00d31aSBartosz Markowski 6875e3dd157SKalle Valo static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb) 6885e3dd157SKalle Valo { 6895e3dd157SKalle Valo struct wmi_scan_event *event = (struct wmi_scan_event *)skb->data; 6905e3dd157SKalle Valo enum wmi_scan_event_type event_type; 6915e3dd157SKalle Valo enum wmi_scan_completion_reason reason; 6925e3dd157SKalle Valo u32 freq; 6935e3dd157SKalle Valo u32 req_id; 6945e3dd157SKalle Valo u32 scan_id; 6955e3dd157SKalle Valo u32 vdev_id; 6965e3dd157SKalle Valo 6975e3dd157SKalle Valo event_type = __le32_to_cpu(event->event_type); 6985e3dd157SKalle Valo reason = __le32_to_cpu(event->reason); 6995e3dd157SKalle Valo freq = __le32_to_cpu(event->channel_freq); 7005e3dd157SKalle Valo req_id = __le32_to_cpu(event->scan_req_id); 7015e3dd157SKalle Valo scan_id = __le32_to_cpu(event->scan_id); 7025e3dd157SKalle Valo vdev_id = __le32_to_cpu(event->vdev_id); 7035e3dd157SKalle Valo 7045e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENTID\n"); 7055e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 7065e3dd157SKalle Valo "scan event type %d reason %d freq %d req_id %d " 7075e3dd157SKalle Valo "scan_id %d vdev_id %d\n", 7085e3dd157SKalle Valo event_type, reason, freq, req_id, scan_id, vdev_id); 7095e3dd157SKalle Valo 7105e3dd157SKalle Valo spin_lock_bh(&ar->data_lock); 7115e3dd157SKalle Valo 7125e3dd157SKalle Valo switch (event_type) { 7135e3dd157SKalle Valo case WMI_SCAN_EVENT_STARTED: 7145e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_STARTED\n"); 7155e3dd157SKalle Valo if (ar->scan.in_progress && ar->scan.is_roc) 7165e3dd157SKalle Valo ieee80211_ready_on_channel(ar->hw); 7175e3dd157SKalle Valo 7185e3dd157SKalle Valo complete(&ar->scan.started); 7195e3dd157SKalle Valo break; 7205e3dd157SKalle Valo case WMI_SCAN_EVENT_COMPLETED: 7215e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_COMPLETED\n"); 7225e3dd157SKalle Valo switch (reason) { 7235e3dd157SKalle Valo case WMI_SCAN_REASON_COMPLETED: 7245e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_COMPLETED\n"); 7255e3dd157SKalle Valo break; 7265e3dd157SKalle Valo case WMI_SCAN_REASON_CANCELLED: 7275e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_CANCELED\n"); 7285e3dd157SKalle Valo break; 7295e3dd157SKalle Valo case WMI_SCAN_REASON_PREEMPTED: 7305e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_PREEMPTED\n"); 7315e3dd157SKalle Valo break; 7325e3dd157SKalle Valo case WMI_SCAN_REASON_TIMEDOUT: 7335e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_TIMEDOUT\n"); 7345e3dd157SKalle Valo break; 7355e3dd157SKalle Valo default: 7365e3dd157SKalle Valo break; 7375e3dd157SKalle Valo } 7385e3dd157SKalle Valo 7395e3dd157SKalle Valo ar->scan_channel = NULL; 7405e3dd157SKalle Valo if (!ar->scan.in_progress) { 7415e3dd157SKalle Valo ath10k_warn("no scan requested, ignoring\n"); 7425e3dd157SKalle Valo break; 7435e3dd157SKalle Valo } 7445e3dd157SKalle Valo 7455e3dd157SKalle Valo if (ar->scan.is_roc) { 7465e3dd157SKalle Valo ath10k_offchan_tx_purge(ar); 7475e3dd157SKalle Valo 7485e3dd157SKalle Valo if (!ar->scan.aborting) 7495e3dd157SKalle Valo ieee80211_remain_on_channel_expired(ar->hw); 7505e3dd157SKalle Valo } else { 7515e3dd157SKalle Valo ieee80211_scan_completed(ar->hw, ar->scan.aborting); 7525e3dd157SKalle Valo } 7535e3dd157SKalle Valo 7545e3dd157SKalle Valo del_timer(&ar->scan.timeout); 7555e3dd157SKalle Valo complete_all(&ar->scan.completed); 7565e3dd157SKalle Valo ar->scan.in_progress = false; 7575e3dd157SKalle Valo break; 7585e3dd157SKalle Valo case WMI_SCAN_EVENT_BSS_CHANNEL: 7595e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_BSS_CHANNEL\n"); 7605e3dd157SKalle Valo ar->scan_channel = NULL; 7615e3dd157SKalle Valo break; 7625e3dd157SKalle Valo case WMI_SCAN_EVENT_FOREIGN_CHANNEL: 7635e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_FOREIGN_CHANNEL\n"); 7645e3dd157SKalle Valo ar->scan_channel = ieee80211_get_channel(ar->hw->wiphy, freq); 7655e3dd157SKalle Valo if (ar->scan.in_progress && ar->scan.is_roc && 7665e3dd157SKalle Valo ar->scan.roc_freq == freq) { 7675e3dd157SKalle Valo complete(&ar->scan.on_channel); 7685e3dd157SKalle Valo } 7695e3dd157SKalle Valo break; 7705e3dd157SKalle Valo case WMI_SCAN_EVENT_DEQUEUED: 7715e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_DEQUEUED\n"); 7725e3dd157SKalle Valo break; 7735e3dd157SKalle Valo case WMI_SCAN_EVENT_PREEMPTED: 7745e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENT_PREEMPTED\n"); 7755e3dd157SKalle Valo break; 7765e3dd157SKalle Valo case WMI_SCAN_EVENT_START_FAILED: 7775e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENT_START_FAILED\n"); 7785e3dd157SKalle Valo break; 7795e3dd157SKalle Valo default: 7805e3dd157SKalle Valo break; 7815e3dd157SKalle Valo } 7825e3dd157SKalle Valo 7835e3dd157SKalle Valo spin_unlock_bh(&ar->data_lock); 7845e3dd157SKalle Valo return 0; 7855e3dd157SKalle Valo } 7865e3dd157SKalle Valo 7875e3dd157SKalle Valo static inline enum ieee80211_band phy_mode_to_band(u32 phy_mode) 7885e3dd157SKalle Valo { 7895e3dd157SKalle Valo enum ieee80211_band band; 7905e3dd157SKalle Valo 7915e3dd157SKalle Valo switch (phy_mode) { 7925e3dd157SKalle Valo case MODE_11A: 7935e3dd157SKalle Valo case MODE_11NA_HT20: 7945e3dd157SKalle Valo case MODE_11NA_HT40: 7955e3dd157SKalle Valo case MODE_11AC_VHT20: 7965e3dd157SKalle Valo case MODE_11AC_VHT40: 7975e3dd157SKalle Valo case MODE_11AC_VHT80: 7985e3dd157SKalle Valo band = IEEE80211_BAND_5GHZ; 7995e3dd157SKalle Valo break; 8005e3dd157SKalle Valo case MODE_11G: 8015e3dd157SKalle Valo case MODE_11B: 8025e3dd157SKalle Valo case MODE_11GONLY: 8035e3dd157SKalle Valo case MODE_11NG_HT20: 8045e3dd157SKalle Valo case MODE_11NG_HT40: 8055e3dd157SKalle Valo case MODE_11AC_VHT20_2G: 8065e3dd157SKalle Valo case MODE_11AC_VHT40_2G: 8075e3dd157SKalle Valo case MODE_11AC_VHT80_2G: 8085e3dd157SKalle Valo default: 8095e3dd157SKalle Valo band = IEEE80211_BAND_2GHZ; 8105e3dd157SKalle Valo } 8115e3dd157SKalle Valo 8125e3dd157SKalle Valo return band; 8135e3dd157SKalle Valo } 8145e3dd157SKalle Valo 8155e3dd157SKalle Valo static inline u8 get_rate_idx(u32 rate, enum ieee80211_band band) 8165e3dd157SKalle Valo { 8175e3dd157SKalle Valo u8 rate_idx = 0; 8185e3dd157SKalle Valo 8195e3dd157SKalle Valo /* rate in Kbps */ 8205e3dd157SKalle Valo switch (rate) { 8215e3dd157SKalle Valo case 1000: 8225e3dd157SKalle Valo rate_idx = 0; 8235e3dd157SKalle Valo break; 8245e3dd157SKalle Valo case 2000: 8255e3dd157SKalle Valo rate_idx = 1; 8265e3dd157SKalle Valo break; 8275e3dd157SKalle Valo case 5500: 8285e3dd157SKalle Valo rate_idx = 2; 8295e3dd157SKalle Valo break; 8305e3dd157SKalle Valo case 11000: 8315e3dd157SKalle Valo rate_idx = 3; 8325e3dd157SKalle Valo break; 8335e3dd157SKalle Valo case 6000: 8345e3dd157SKalle Valo rate_idx = 4; 8355e3dd157SKalle Valo break; 8365e3dd157SKalle Valo case 9000: 8375e3dd157SKalle Valo rate_idx = 5; 8385e3dd157SKalle Valo break; 8395e3dd157SKalle Valo case 12000: 8405e3dd157SKalle Valo rate_idx = 6; 8415e3dd157SKalle Valo break; 8425e3dd157SKalle Valo case 18000: 8435e3dd157SKalle Valo rate_idx = 7; 8445e3dd157SKalle Valo break; 8455e3dd157SKalle Valo case 24000: 8465e3dd157SKalle Valo rate_idx = 8; 8475e3dd157SKalle Valo break; 8485e3dd157SKalle Valo case 36000: 8495e3dd157SKalle Valo rate_idx = 9; 8505e3dd157SKalle Valo break; 8515e3dd157SKalle Valo case 48000: 8525e3dd157SKalle Valo rate_idx = 10; 8535e3dd157SKalle Valo break; 8545e3dd157SKalle Valo case 54000: 8555e3dd157SKalle Valo rate_idx = 11; 8565e3dd157SKalle Valo break; 8575e3dd157SKalle Valo default: 8585e3dd157SKalle Valo break; 8595e3dd157SKalle Valo } 8605e3dd157SKalle Valo 8615e3dd157SKalle Valo if (band == IEEE80211_BAND_5GHZ) { 8625e3dd157SKalle Valo if (rate_idx > 3) 8635e3dd157SKalle Valo /* Omit CCK rates */ 8645e3dd157SKalle Valo rate_idx -= 4; 8655e3dd157SKalle Valo else 8665e3dd157SKalle Valo rate_idx = 0; 8675e3dd157SKalle Valo } 8685e3dd157SKalle Valo 8695e3dd157SKalle Valo return rate_idx; 8705e3dd157SKalle Valo } 8715e3dd157SKalle Valo 8725e3dd157SKalle Valo static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) 8735e3dd157SKalle Valo { 8740d9b0438SMichal Kazior struct wmi_mgmt_rx_event_v1 *ev_v1; 8750d9b0438SMichal Kazior struct wmi_mgmt_rx_event_v2 *ev_v2; 8760d9b0438SMichal Kazior struct wmi_mgmt_rx_hdr_v1 *ev_hdr; 8775e3dd157SKalle Valo struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 8785e3dd157SKalle Valo struct ieee80211_hdr *hdr; 8795e3dd157SKalle Valo u32 rx_status; 8805e3dd157SKalle Valo u32 channel; 8815e3dd157SKalle Valo u32 phy_mode; 8825e3dd157SKalle Valo u32 snr; 8835e3dd157SKalle Valo u32 rate; 8845e3dd157SKalle Valo u32 buf_len; 8855e3dd157SKalle Valo u16 fc; 8860d9b0438SMichal Kazior int pull_len; 8875e3dd157SKalle Valo 8880d9b0438SMichal Kazior if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) { 8890d9b0438SMichal Kazior ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data; 8900d9b0438SMichal Kazior ev_hdr = &ev_v2->hdr.v1; 8910d9b0438SMichal Kazior pull_len = sizeof(*ev_v2); 8920d9b0438SMichal Kazior } else { 8930d9b0438SMichal Kazior ev_v1 = (struct wmi_mgmt_rx_event_v1 *)skb->data; 8940d9b0438SMichal Kazior ev_hdr = &ev_v1->hdr; 8950d9b0438SMichal Kazior pull_len = sizeof(*ev_v1); 8960d9b0438SMichal Kazior } 8970d9b0438SMichal Kazior 8980d9b0438SMichal Kazior channel = __le32_to_cpu(ev_hdr->channel); 8990d9b0438SMichal Kazior buf_len = __le32_to_cpu(ev_hdr->buf_len); 9000d9b0438SMichal Kazior rx_status = __le32_to_cpu(ev_hdr->status); 9010d9b0438SMichal Kazior snr = __le32_to_cpu(ev_hdr->snr); 9020d9b0438SMichal Kazior phy_mode = __le32_to_cpu(ev_hdr->phy_mode); 9030d9b0438SMichal Kazior rate = __le32_to_cpu(ev_hdr->rate); 9045e3dd157SKalle Valo 9055e3dd157SKalle Valo memset(status, 0, sizeof(*status)); 9065e3dd157SKalle Valo 9075e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, 9085e3dd157SKalle Valo "event mgmt rx status %08x\n", rx_status); 9095e3dd157SKalle Valo 9105e3dd157SKalle Valo if (rx_status & WMI_RX_STATUS_ERR_DECRYPT) { 9115e3dd157SKalle Valo dev_kfree_skb(skb); 9125e3dd157SKalle Valo return 0; 9135e3dd157SKalle Valo } 9145e3dd157SKalle Valo 9155e3dd157SKalle Valo if (rx_status & WMI_RX_STATUS_ERR_KEY_CACHE_MISS) { 9165e3dd157SKalle Valo dev_kfree_skb(skb); 9175e3dd157SKalle Valo return 0; 9185e3dd157SKalle Valo } 9195e3dd157SKalle Valo 9205e3dd157SKalle Valo if (rx_status & WMI_RX_STATUS_ERR_CRC) 9215e3dd157SKalle Valo status->flag |= RX_FLAG_FAILED_FCS_CRC; 9225e3dd157SKalle Valo if (rx_status & WMI_RX_STATUS_ERR_MIC) 9235e3dd157SKalle Valo status->flag |= RX_FLAG_MMIC_ERROR; 9245e3dd157SKalle Valo 9255e3dd157SKalle Valo status->band = phy_mode_to_band(phy_mode); 9265e3dd157SKalle Valo status->freq = ieee80211_channel_to_frequency(channel, status->band); 9275e3dd157SKalle Valo status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; 9285e3dd157SKalle Valo status->rate_idx = get_rate_idx(rate, status->band); 9295e3dd157SKalle Valo 9300d9b0438SMichal Kazior skb_pull(skb, pull_len); 9315e3dd157SKalle Valo 9325e3dd157SKalle Valo hdr = (struct ieee80211_hdr *)skb->data; 9335e3dd157SKalle Valo fc = le16_to_cpu(hdr->frame_control); 9345e3dd157SKalle Valo 9355e3dd157SKalle Valo if (fc & IEEE80211_FCTL_PROTECTED) { 9365e3dd157SKalle Valo status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED | 9375e3dd157SKalle Valo RX_FLAG_MMIC_STRIPPED; 9385e3dd157SKalle Valo hdr->frame_control = __cpu_to_le16(fc & 9395e3dd157SKalle Valo ~IEEE80211_FCTL_PROTECTED); 9405e3dd157SKalle Valo } 9415e3dd157SKalle Valo 9425e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, 9435e3dd157SKalle Valo "event mgmt rx skb %p len %d ftype %02x stype %02x\n", 9445e3dd157SKalle Valo skb, skb->len, 9455e3dd157SKalle Valo fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE); 9465e3dd157SKalle Valo 9475e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, 9485e3dd157SKalle Valo "event mgmt rx freq %d band %d snr %d, rate_idx %d\n", 9495e3dd157SKalle Valo status->freq, status->band, status->signal, 9505e3dd157SKalle Valo status->rate_idx); 9515e3dd157SKalle Valo 9525e3dd157SKalle Valo /* 9535e3dd157SKalle Valo * packets from HTC come aligned to 4byte boundaries 9545e3dd157SKalle Valo * because they can originally come in along with a trailer 9555e3dd157SKalle Valo */ 9565e3dd157SKalle Valo skb_trim(skb, buf_len); 9575e3dd157SKalle Valo 9585e3dd157SKalle Valo ieee80211_rx(ar->hw, skb); 9595e3dd157SKalle Valo return 0; 9605e3dd157SKalle Valo } 9615e3dd157SKalle Valo 9622e1dea40SMichal Kazior static int freq_to_idx(struct ath10k *ar, int freq) 9632e1dea40SMichal Kazior { 9642e1dea40SMichal Kazior struct ieee80211_supported_band *sband; 9652e1dea40SMichal Kazior int band, ch, idx = 0; 9662e1dea40SMichal Kazior 9672e1dea40SMichal Kazior for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { 9682e1dea40SMichal Kazior sband = ar->hw->wiphy->bands[band]; 9692e1dea40SMichal Kazior if (!sband) 9702e1dea40SMichal Kazior continue; 9712e1dea40SMichal Kazior 9722e1dea40SMichal Kazior for (ch = 0; ch < sband->n_channels; ch++, idx++) 9732e1dea40SMichal Kazior if (sband->channels[ch].center_freq == freq) 9742e1dea40SMichal Kazior goto exit; 9752e1dea40SMichal Kazior } 9762e1dea40SMichal Kazior 9772e1dea40SMichal Kazior exit: 9782e1dea40SMichal Kazior return idx; 9792e1dea40SMichal Kazior } 9802e1dea40SMichal Kazior 9815e3dd157SKalle Valo static void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb) 9825e3dd157SKalle Valo { 9832e1dea40SMichal Kazior struct wmi_chan_info_event *ev; 9842e1dea40SMichal Kazior struct survey_info *survey; 9852e1dea40SMichal Kazior u32 err_code, freq, cmd_flags, noise_floor, rx_clear_count, cycle_count; 9862e1dea40SMichal Kazior int idx; 9872e1dea40SMichal Kazior 9882e1dea40SMichal Kazior ev = (struct wmi_chan_info_event *)skb->data; 9892e1dea40SMichal Kazior 9902e1dea40SMichal Kazior err_code = __le32_to_cpu(ev->err_code); 9912e1dea40SMichal Kazior freq = __le32_to_cpu(ev->freq); 9922e1dea40SMichal Kazior cmd_flags = __le32_to_cpu(ev->cmd_flags); 9932e1dea40SMichal Kazior noise_floor = __le32_to_cpu(ev->noise_floor); 9942e1dea40SMichal Kazior rx_clear_count = __le32_to_cpu(ev->rx_clear_count); 9952e1dea40SMichal Kazior cycle_count = __le32_to_cpu(ev->cycle_count); 9962e1dea40SMichal Kazior 9972e1dea40SMichal Kazior ath10k_dbg(ATH10K_DBG_WMI, 9982e1dea40SMichal Kazior "chan info err_code %d freq %d cmd_flags %d noise_floor %d rx_clear_count %d cycle_count %d\n", 9992e1dea40SMichal Kazior err_code, freq, cmd_flags, noise_floor, rx_clear_count, 10002e1dea40SMichal Kazior cycle_count); 10012e1dea40SMichal Kazior 10022e1dea40SMichal Kazior spin_lock_bh(&ar->data_lock); 10032e1dea40SMichal Kazior 10042e1dea40SMichal Kazior if (!ar->scan.in_progress) { 10052e1dea40SMichal Kazior ath10k_warn("chan info event without a scan request?\n"); 10062e1dea40SMichal Kazior goto exit; 10072e1dea40SMichal Kazior } 10082e1dea40SMichal Kazior 10092e1dea40SMichal Kazior idx = freq_to_idx(ar, freq); 10102e1dea40SMichal Kazior if (idx >= ARRAY_SIZE(ar->survey)) { 10112e1dea40SMichal Kazior ath10k_warn("chan info: invalid frequency %d (idx %d out of bounds)\n", 10122e1dea40SMichal Kazior freq, idx); 10132e1dea40SMichal Kazior goto exit; 10142e1dea40SMichal Kazior } 10152e1dea40SMichal Kazior 10162e1dea40SMichal Kazior if (cmd_flags & WMI_CHAN_INFO_FLAG_COMPLETE) { 10172e1dea40SMichal Kazior /* During scanning chan info is reported twice for each 10182e1dea40SMichal Kazior * visited channel. The reported cycle count is global 10192e1dea40SMichal Kazior * and per-channel cycle count must be calculated */ 10202e1dea40SMichal Kazior 10212e1dea40SMichal Kazior cycle_count -= ar->survey_last_cycle_count; 10222e1dea40SMichal Kazior rx_clear_count -= ar->survey_last_rx_clear_count; 10232e1dea40SMichal Kazior 10242e1dea40SMichal Kazior survey = &ar->survey[idx]; 10252e1dea40SMichal Kazior survey->channel_time = WMI_CHAN_INFO_MSEC(cycle_count); 10262e1dea40SMichal Kazior survey->channel_time_rx = WMI_CHAN_INFO_MSEC(rx_clear_count); 10272e1dea40SMichal Kazior survey->noise = noise_floor; 10282e1dea40SMichal Kazior survey->filled = SURVEY_INFO_CHANNEL_TIME | 10292e1dea40SMichal Kazior SURVEY_INFO_CHANNEL_TIME_RX | 10302e1dea40SMichal Kazior SURVEY_INFO_NOISE_DBM; 10312e1dea40SMichal Kazior } 10322e1dea40SMichal Kazior 10332e1dea40SMichal Kazior ar->survey_last_rx_clear_count = rx_clear_count; 10342e1dea40SMichal Kazior ar->survey_last_cycle_count = cycle_count; 10352e1dea40SMichal Kazior 10362e1dea40SMichal Kazior exit: 10372e1dea40SMichal Kazior spin_unlock_bh(&ar->data_lock); 10385e3dd157SKalle Valo } 10395e3dd157SKalle Valo 10405e3dd157SKalle Valo static void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb) 10415e3dd157SKalle Valo { 10425e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_ECHO_EVENTID\n"); 10435e3dd157SKalle Valo } 10445e3dd157SKalle Valo 10455e3dd157SKalle Valo static void ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb) 10465e3dd157SKalle Valo { 10475e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_DEBUG_MESG_EVENTID\n"); 10485e3dd157SKalle Valo } 10495e3dd157SKalle Valo 10505e3dd157SKalle Valo static void ath10k_wmi_event_update_stats(struct ath10k *ar, 10515e3dd157SKalle Valo struct sk_buff *skb) 10525e3dd157SKalle Valo { 10535e3dd157SKalle Valo struct wmi_stats_event *ev = (struct wmi_stats_event *)skb->data; 10545e3dd157SKalle Valo 10555e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n"); 10565e3dd157SKalle Valo 10575e3dd157SKalle Valo ath10k_debug_read_target_stats(ar, ev); 10585e3dd157SKalle Valo } 10595e3dd157SKalle Valo 10605e3dd157SKalle Valo static void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, 10615e3dd157SKalle Valo struct sk_buff *skb) 10625e3dd157SKalle Valo { 10635e3dd157SKalle Valo struct wmi_vdev_start_response_event *ev; 10645e3dd157SKalle Valo 10655e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_START_RESP_EVENTID\n"); 10665e3dd157SKalle Valo 10675e3dd157SKalle Valo ev = (struct wmi_vdev_start_response_event *)skb->data; 10685e3dd157SKalle Valo 10695e3dd157SKalle Valo if (WARN_ON(__le32_to_cpu(ev->status))) 10705e3dd157SKalle Valo return; 10715e3dd157SKalle Valo 10725e3dd157SKalle Valo complete(&ar->vdev_setup_done); 10735e3dd157SKalle Valo } 10745e3dd157SKalle Valo 10755e3dd157SKalle Valo static void ath10k_wmi_event_vdev_stopped(struct ath10k *ar, 10765e3dd157SKalle Valo struct sk_buff *skb) 10775e3dd157SKalle Valo { 10785e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_STOPPED_EVENTID\n"); 10795e3dd157SKalle Valo complete(&ar->vdev_setup_done); 10805e3dd157SKalle Valo } 10815e3dd157SKalle Valo 10825e3dd157SKalle Valo static void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar, 10835e3dd157SKalle Valo struct sk_buff *skb) 10845e3dd157SKalle Valo { 10855e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_PEER_STA_KICKOUT_EVENTID\n"); 10865e3dd157SKalle Valo } 10875e3dd157SKalle Valo 10885e3dd157SKalle Valo /* 10895e3dd157SKalle Valo * FIXME 10905e3dd157SKalle Valo * 10915e3dd157SKalle Valo * We don't report to mac80211 sleep state of connected 10925e3dd157SKalle Valo * stations. Due to this mac80211 can't fill in TIM IE 10935e3dd157SKalle Valo * correctly. 10945e3dd157SKalle Valo * 10955e3dd157SKalle Valo * I know of no way of getting nullfunc frames that contain 10965e3dd157SKalle Valo * sleep transition from connected stations - these do not 10975e3dd157SKalle Valo * seem to be sent from the target to the host. There also 10985e3dd157SKalle Valo * doesn't seem to be a dedicated event for that. So the 10995e3dd157SKalle Valo * only way left to do this would be to read tim_bitmap 11005e3dd157SKalle Valo * during SWBA. 11015e3dd157SKalle Valo * 11025e3dd157SKalle Valo * We could probably try using tim_bitmap from SWBA to tell 11035e3dd157SKalle Valo * mac80211 which stations are asleep and which are not. The 11045e3dd157SKalle Valo * problem here is calling mac80211 functions so many times 11055e3dd157SKalle Valo * could take too long and make us miss the time to submit 11065e3dd157SKalle Valo * the beacon to the target. 11075e3dd157SKalle Valo * 11085e3dd157SKalle Valo * So as a workaround we try to extend the TIM IE if there 11095e3dd157SKalle Valo * is unicast buffered for stations with aid > 7 and fill it 11105e3dd157SKalle Valo * in ourselves. 11115e3dd157SKalle Valo */ 11125e3dd157SKalle Valo static void ath10k_wmi_update_tim(struct ath10k *ar, 11135e3dd157SKalle Valo struct ath10k_vif *arvif, 11145e3dd157SKalle Valo struct sk_buff *bcn, 11155e3dd157SKalle Valo struct wmi_bcn_info *bcn_info) 11165e3dd157SKalle Valo { 11175e3dd157SKalle Valo struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)bcn->data; 11185e3dd157SKalle Valo struct ieee80211_tim_ie *tim; 11195e3dd157SKalle Valo u8 *ies, *ie; 11205e3dd157SKalle Valo u8 ie_len, pvm_len; 11215e3dd157SKalle Valo 11225e3dd157SKalle Valo /* if next SWBA has no tim_changed the tim_bitmap is garbage. 11235e3dd157SKalle Valo * we must copy the bitmap upon change and reuse it later */ 11245e3dd157SKalle Valo if (__le32_to_cpu(bcn_info->tim_info.tim_changed)) { 11255e3dd157SKalle Valo int i; 11265e3dd157SKalle Valo 11275e3dd157SKalle Valo BUILD_BUG_ON(sizeof(arvif->u.ap.tim_bitmap) != 11285e3dd157SKalle Valo sizeof(bcn_info->tim_info.tim_bitmap)); 11295e3dd157SKalle Valo 11305e3dd157SKalle Valo for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++) { 11315e3dd157SKalle Valo __le32 t = bcn_info->tim_info.tim_bitmap[i / 4]; 11325e3dd157SKalle Valo u32 v = __le32_to_cpu(t); 11335e3dd157SKalle Valo arvif->u.ap.tim_bitmap[i] = (v >> ((i % 4) * 8)) & 0xFF; 11345e3dd157SKalle Valo } 11355e3dd157SKalle Valo 11365e3dd157SKalle Valo /* FW reports either length 0 or 16 11375e3dd157SKalle Valo * so we calculate this on our own */ 11385e3dd157SKalle Valo arvif->u.ap.tim_len = 0; 11395e3dd157SKalle Valo for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++) 11405e3dd157SKalle Valo if (arvif->u.ap.tim_bitmap[i]) 11415e3dd157SKalle Valo arvif->u.ap.tim_len = i; 11425e3dd157SKalle Valo 11435e3dd157SKalle Valo arvif->u.ap.tim_len++; 11445e3dd157SKalle Valo } 11455e3dd157SKalle Valo 11465e3dd157SKalle Valo ies = bcn->data; 11475e3dd157SKalle Valo ies += ieee80211_hdrlen(hdr->frame_control); 11485e3dd157SKalle Valo ies += 12; /* fixed parameters */ 11495e3dd157SKalle Valo 11505e3dd157SKalle Valo ie = (u8 *)cfg80211_find_ie(WLAN_EID_TIM, ies, 11515e3dd157SKalle Valo (u8 *)skb_tail_pointer(bcn) - ies); 11525e3dd157SKalle Valo if (!ie) { 115309af8f85SMichal Kazior if (arvif->vdev_type != WMI_VDEV_TYPE_IBSS) 11545e3dd157SKalle Valo ath10k_warn("no tim ie found;\n"); 11555e3dd157SKalle Valo return; 11565e3dd157SKalle Valo } 11575e3dd157SKalle Valo 11585e3dd157SKalle Valo tim = (void *)ie + 2; 11595e3dd157SKalle Valo ie_len = ie[1]; 11605e3dd157SKalle Valo pvm_len = ie_len - 3; /* exclude dtim count, dtim period, bmap ctl */ 11615e3dd157SKalle Valo 11625e3dd157SKalle Valo if (pvm_len < arvif->u.ap.tim_len) { 11635e3dd157SKalle Valo int expand_size = sizeof(arvif->u.ap.tim_bitmap) - pvm_len; 11645e3dd157SKalle Valo int move_size = skb_tail_pointer(bcn) - (ie + 2 + ie_len); 11655e3dd157SKalle Valo void *next_ie = ie + 2 + ie_len; 11665e3dd157SKalle Valo 11675e3dd157SKalle Valo if (skb_put(bcn, expand_size)) { 11685e3dd157SKalle Valo memmove(next_ie + expand_size, next_ie, move_size); 11695e3dd157SKalle Valo 11705e3dd157SKalle Valo ie[1] += expand_size; 11715e3dd157SKalle Valo ie_len += expand_size; 11725e3dd157SKalle Valo pvm_len += expand_size; 11735e3dd157SKalle Valo } else { 11745e3dd157SKalle Valo ath10k_warn("tim expansion failed\n"); 11755e3dd157SKalle Valo } 11765e3dd157SKalle Valo } 11775e3dd157SKalle Valo 11785e3dd157SKalle Valo if (pvm_len > sizeof(arvif->u.ap.tim_bitmap)) { 11795e3dd157SKalle Valo ath10k_warn("tim pvm length is too great (%d)\n", pvm_len); 11805e3dd157SKalle Valo return; 11815e3dd157SKalle Valo } 11825e3dd157SKalle Valo 11835e3dd157SKalle Valo tim->bitmap_ctrl = !!__le32_to_cpu(bcn_info->tim_info.tim_mcast); 11845e3dd157SKalle Valo memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len); 11855e3dd157SKalle Valo 11865e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n", 11875e3dd157SKalle Valo tim->dtim_count, tim->dtim_period, 11885e3dd157SKalle Valo tim->bitmap_ctrl, pvm_len); 11895e3dd157SKalle Valo } 11905e3dd157SKalle Valo 11915e3dd157SKalle Valo static void ath10k_p2p_fill_noa_ie(u8 *data, u32 len, 11925e3dd157SKalle Valo struct wmi_p2p_noa_info *noa) 11935e3dd157SKalle Valo { 11945e3dd157SKalle Valo struct ieee80211_p2p_noa_attr *noa_attr; 11955e3dd157SKalle Valo u8 ctwindow_oppps = noa->ctwindow_oppps; 11965e3dd157SKalle Valo u8 ctwindow = ctwindow_oppps >> WMI_P2P_OPPPS_CTWINDOW_OFFSET; 11975e3dd157SKalle Valo bool oppps = !!(ctwindow_oppps & WMI_P2P_OPPPS_ENABLE_BIT); 11985e3dd157SKalle Valo __le16 *noa_attr_len; 11995e3dd157SKalle Valo u16 attr_len; 12005e3dd157SKalle Valo u8 noa_descriptors = noa->num_descriptors; 12015e3dd157SKalle Valo int i; 12025e3dd157SKalle Valo 12035e3dd157SKalle Valo /* P2P IE */ 12045e3dd157SKalle Valo data[0] = WLAN_EID_VENDOR_SPECIFIC; 12055e3dd157SKalle Valo data[1] = len - 2; 12065e3dd157SKalle Valo data[2] = (WLAN_OUI_WFA >> 16) & 0xff; 12075e3dd157SKalle Valo data[3] = (WLAN_OUI_WFA >> 8) & 0xff; 12085e3dd157SKalle Valo data[4] = (WLAN_OUI_WFA >> 0) & 0xff; 12095e3dd157SKalle Valo data[5] = WLAN_OUI_TYPE_WFA_P2P; 12105e3dd157SKalle Valo 12115e3dd157SKalle Valo /* NOA ATTR */ 12125e3dd157SKalle Valo data[6] = IEEE80211_P2P_ATTR_ABSENCE_NOTICE; 12135e3dd157SKalle Valo noa_attr_len = (__le16 *)&data[7]; /* 2 bytes */ 12145e3dd157SKalle Valo noa_attr = (struct ieee80211_p2p_noa_attr *)&data[9]; 12155e3dd157SKalle Valo 12165e3dd157SKalle Valo noa_attr->index = noa->index; 12175e3dd157SKalle Valo noa_attr->oppps_ctwindow = ctwindow; 12185e3dd157SKalle Valo if (oppps) 12195e3dd157SKalle Valo noa_attr->oppps_ctwindow |= IEEE80211_P2P_OPPPS_ENABLE_BIT; 12205e3dd157SKalle Valo 12215e3dd157SKalle Valo for (i = 0; i < noa_descriptors; i++) { 12225e3dd157SKalle Valo noa_attr->desc[i].count = 12235e3dd157SKalle Valo __le32_to_cpu(noa->descriptors[i].type_count); 12245e3dd157SKalle Valo noa_attr->desc[i].duration = noa->descriptors[i].duration; 12255e3dd157SKalle Valo noa_attr->desc[i].interval = noa->descriptors[i].interval; 12265e3dd157SKalle Valo noa_attr->desc[i].start_time = noa->descriptors[i].start_time; 12275e3dd157SKalle Valo } 12285e3dd157SKalle Valo 12295e3dd157SKalle Valo attr_len = 2; /* index + oppps_ctwindow */ 12305e3dd157SKalle Valo attr_len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc); 12315e3dd157SKalle Valo *noa_attr_len = __cpu_to_le16(attr_len); 12325e3dd157SKalle Valo } 12335e3dd157SKalle Valo 12345e3dd157SKalle Valo static u32 ath10k_p2p_calc_noa_ie_len(struct wmi_p2p_noa_info *noa) 12355e3dd157SKalle Valo { 12365e3dd157SKalle Valo u32 len = 0; 12375e3dd157SKalle Valo u8 noa_descriptors = noa->num_descriptors; 12385e3dd157SKalle Valo u8 opp_ps_info = noa->ctwindow_oppps; 12395e3dd157SKalle Valo bool opps_enabled = !!(opp_ps_info & WMI_P2P_OPPPS_ENABLE_BIT); 12405e3dd157SKalle Valo 12415e3dd157SKalle Valo 12425e3dd157SKalle Valo if (!noa_descriptors && !opps_enabled) 12435e3dd157SKalle Valo return len; 12445e3dd157SKalle Valo 12455e3dd157SKalle Valo len += 1 + 1 + 4; /* EID + len + OUI */ 12465e3dd157SKalle Valo len += 1 + 2; /* noa attr + attr len */ 12475e3dd157SKalle Valo len += 1 + 1; /* index + oppps_ctwindow */ 12485e3dd157SKalle Valo len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc); 12495e3dd157SKalle Valo 12505e3dd157SKalle Valo return len; 12515e3dd157SKalle Valo } 12525e3dd157SKalle Valo 12535e3dd157SKalle Valo static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif, 12545e3dd157SKalle Valo struct sk_buff *bcn, 12555e3dd157SKalle Valo struct wmi_bcn_info *bcn_info) 12565e3dd157SKalle Valo { 12575e3dd157SKalle Valo struct wmi_p2p_noa_info *noa = &bcn_info->p2p_noa_info; 12585e3dd157SKalle Valo u8 *new_data, *old_data = arvif->u.ap.noa_data; 12595e3dd157SKalle Valo u32 new_len; 12605e3dd157SKalle Valo 12615e3dd157SKalle Valo if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) 12625e3dd157SKalle Valo return; 12635e3dd157SKalle Valo 12645e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, "noa changed: %d\n", noa->changed); 12655e3dd157SKalle Valo if (noa->changed & WMI_P2P_NOA_CHANGED_BIT) { 12665e3dd157SKalle Valo new_len = ath10k_p2p_calc_noa_ie_len(noa); 12675e3dd157SKalle Valo if (!new_len) 12685e3dd157SKalle Valo goto cleanup; 12695e3dd157SKalle Valo 12705e3dd157SKalle Valo new_data = kmalloc(new_len, GFP_ATOMIC); 12715e3dd157SKalle Valo if (!new_data) 12725e3dd157SKalle Valo goto cleanup; 12735e3dd157SKalle Valo 12745e3dd157SKalle Valo ath10k_p2p_fill_noa_ie(new_data, new_len, noa); 12755e3dd157SKalle Valo 12765e3dd157SKalle Valo spin_lock_bh(&ar->data_lock); 12775e3dd157SKalle Valo arvif->u.ap.noa_data = new_data; 12785e3dd157SKalle Valo arvif->u.ap.noa_len = new_len; 12795e3dd157SKalle Valo spin_unlock_bh(&ar->data_lock); 12805e3dd157SKalle Valo kfree(old_data); 12815e3dd157SKalle Valo } 12825e3dd157SKalle Valo 12835e3dd157SKalle Valo if (arvif->u.ap.noa_data) 12845e3dd157SKalle Valo if (!pskb_expand_head(bcn, 0, arvif->u.ap.noa_len, GFP_ATOMIC)) 12855e3dd157SKalle Valo memcpy(skb_put(bcn, arvif->u.ap.noa_len), 12865e3dd157SKalle Valo arvif->u.ap.noa_data, 12875e3dd157SKalle Valo arvif->u.ap.noa_len); 12885e3dd157SKalle Valo return; 12895e3dd157SKalle Valo 12905e3dd157SKalle Valo cleanup: 12915e3dd157SKalle Valo spin_lock_bh(&ar->data_lock); 12925e3dd157SKalle Valo arvif->u.ap.noa_data = NULL; 12935e3dd157SKalle Valo arvif->u.ap.noa_len = 0; 12945e3dd157SKalle Valo spin_unlock_bh(&ar->data_lock); 12955e3dd157SKalle Valo kfree(old_data); 12965e3dd157SKalle Valo } 12975e3dd157SKalle Valo 12985e3dd157SKalle Valo 12995e3dd157SKalle Valo static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) 13005e3dd157SKalle Valo { 13015e3dd157SKalle Valo struct wmi_host_swba_event *ev; 13025e3dd157SKalle Valo u32 map; 13035e3dd157SKalle Valo int i = -1; 13045e3dd157SKalle Valo struct wmi_bcn_info *bcn_info; 13055e3dd157SKalle Valo struct ath10k_vif *arvif; 13065e3dd157SKalle Valo struct sk_buff *bcn; 13075e3dd157SKalle Valo int vdev_id = 0; 13085e3dd157SKalle Valo 13095e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, "WMI_HOST_SWBA_EVENTID\n"); 13105e3dd157SKalle Valo 13115e3dd157SKalle Valo ev = (struct wmi_host_swba_event *)skb->data; 13125e3dd157SKalle Valo map = __le32_to_cpu(ev->vdev_map); 13135e3dd157SKalle Valo 13145e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, "host swba:\n" 13155e3dd157SKalle Valo "-vdev map 0x%x\n", 13165e3dd157SKalle Valo ev->vdev_map); 13175e3dd157SKalle Valo 13185e3dd157SKalle Valo for (; map; map >>= 1, vdev_id++) { 13195e3dd157SKalle Valo if (!(map & 0x1)) 13205e3dd157SKalle Valo continue; 13215e3dd157SKalle Valo 13225e3dd157SKalle Valo i++; 13235e3dd157SKalle Valo 13245e3dd157SKalle Valo if (i >= WMI_MAX_AP_VDEV) { 13255e3dd157SKalle Valo ath10k_warn("swba has corrupted vdev map\n"); 13265e3dd157SKalle Valo break; 13275e3dd157SKalle Valo } 13285e3dd157SKalle Valo 13295e3dd157SKalle Valo bcn_info = &ev->bcn_info[i]; 13305e3dd157SKalle Valo 13315e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_MGMT, 13325e3dd157SKalle Valo "-bcn_info[%d]:\n" 13335e3dd157SKalle Valo "--tim_len %d\n" 13345e3dd157SKalle Valo "--tim_mcast %d\n" 13355e3dd157SKalle Valo "--tim_changed %d\n" 13365e3dd157SKalle Valo "--tim_num_ps_pending %d\n" 13375e3dd157SKalle Valo "--tim_bitmap 0x%08x%08x%08x%08x\n", 13385e3dd157SKalle Valo i, 13395e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_len), 13405e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_mcast), 13415e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_changed), 13425e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_num_ps_pending), 13435e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_bitmap[3]), 13445e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_bitmap[2]), 13455e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_bitmap[1]), 13465e3dd157SKalle Valo __le32_to_cpu(bcn_info->tim_info.tim_bitmap[0])); 13475e3dd157SKalle Valo 13485e3dd157SKalle Valo arvif = ath10k_get_arvif(ar, vdev_id); 13495e3dd157SKalle Valo if (arvif == NULL) { 13505e3dd157SKalle Valo ath10k_warn("no vif for vdev_id %d found\n", vdev_id); 13515e3dd157SKalle Valo continue; 13525e3dd157SKalle Valo } 13535e3dd157SKalle Valo 13545e3dd157SKalle Valo bcn = ieee80211_beacon_get(ar->hw, arvif->vif); 13555e3dd157SKalle Valo if (!bcn) { 13565e3dd157SKalle Valo ath10k_warn("could not get mac80211 beacon\n"); 13575e3dd157SKalle Valo continue; 13585e3dd157SKalle Valo } 13595e3dd157SKalle Valo 13605e3dd157SKalle Valo ath10k_tx_h_seq_no(bcn); 13615e3dd157SKalle Valo ath10k_wmi_update_tim(ar, arvif, bcn, bcn_info); 13625e3dd157SKalle Valo ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info); 13635e3dd157SKalle Valo 1364ed54388aSMichal Kazior spin_lock_bh(&ar->data_lock); 1365ed54388aSMichal Kazior if (arvif->beacon) { 1366ed54388aSMichal Kazior ath10k_warn("SWBA overrun on vdev %d\n", 1367ed54388aSMichal Kazior arvif->vdev_id); 1368ed54388aSMichal Kazior dev_kfree_skb_any(arvif->beacon); 1369ed54388aSMichal Kazior } 13705e3dd157SKalle Valo 1371ed54388aSMichal Kazior arvif->beacon = bcn; 13725e3dd157SKalle Valo 1373ed54388aSMichal Kazior ath10k_wmi_tx_beacon_nowait(arvif); 1374ed54388aSMichal Kazior spin_unlock_bh(&ar->data_lock); 13755e3dd157SKalle Valo } 13765e3dd157SKalle Valo } 13775e3dd157SKalle Valo 13785e3dd157SKalle Valo static void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, 13795e3dd157SKalle Valo struct sk_buff *skb) 13805e3dd157SKalle Valo { 13815e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_TBTTOFFSET_UPDATE_EVENTID\n"); 13825e3dd157SKalle Valo } 13835e3dd157SKalle Valo 13845e3dd157SKalle Valo static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) 13855e3dd157SKalle Valo { 13865e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_PHYERR_EVENTID\n"); 13875e3dd157SKalle Valo } 13885e3dd157SKalle Valo 13895e3dd157SKalle Valo static void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb) 13905e3dd157SKalle Valo { 13915e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_ROAM_EVENTID\n"); 13925e3dd157SKalle Valo } 13935e3dd157SKalle Valo 13945e3dd157SKalle Valo static void ath10k_wmi_event_profile_match(struct ath10k *ar, 13955e3dd157SKalle Valo struct sk_buff *skb) 13965e3dd157SKalle Valo { 13975e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_PROFILE_MATCH\n"); 13985e3dd157SKalle Valo } 13995e3dd157SKalle Valo 14005e3dd157SKalle Valo static void ath10k_wmi_event_debug_print(struct ath10k *ar, 14015e3dd157SKalle Valo struct sk_buff *skb) 14025e3dd157SKalle Valo { 14035e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_DEBUG_PRINT_EVENTID\n"); 14045e3dd157SKalle Valo } 14055e3dd157SKalle Valo 14065e3dd157SKalle Valo static void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb) 14075e3dd157SKalle Valo { 14085e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_PDEV_QVIT_EVENTID\n"); 14095e3dd157SKalle Valo } 14105e3dd157SKalle Valo 14115e3dd157SKalle Valo static void ath10k_wmi_event_wlan_profile_data(struct ath10k *ar, 14125e3dd157SKalle Valo struct sk_buff *skb) 14135e3dd157SKalle Valo { 14145e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_WLAN_PROFILE_DATA_EVENTID\n"); 14155e3dd157SKalle Valo } 14165e3dd157SKalle Valo 14175e3dd157SKalle Valo static void ath10k_wmi_event_rtt_measurement_report(struct ath10k *ar, 14185e3dd157SKalle Valo struct sk_buff *skb) 14195e3dd157SKalle Valo { 14205e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_RTT_MEASUREMENT_REPORT_EVENTID\n"); 14215e3dd157SKalle Valo } 14225e3dd157SKalle Valo 14235e3dd157SKalle Valo static void ath10k_wmi_event_tsf_measurement_report(struct ath10k *ar, 14245e3dd157SKalle Valo struct sk_buff *skb) 14255e3dd157SKalle Valo { 14265e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_TSF_MEASUREMENT_REPORT_EVENTID\n"); 14275e3dd157SKalle Valo } 14285e3dd157SKalle Valo 14295e3dd157SKalle Valo static void ath10k_wmi_event_rtt_error_report(struct ath10k *ar, 14305e3dd157SKalle Valo struct sk_buff *skb) 14315e3dd157SKalle Valo { 14325e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_RTT_ERROR_REPORT_EVENTID\n"); 14335e3dd157SKalle Valo } 14345e3dd157SKalle Valo 14355e3dd157SKalle Valo static void ath10k_wmi_event_wow_wakeup_host(struct ath10k *ar, 14365e3dd157SKalle Valo struct sk_buff *skb) 14375e3dd157SKalle Valo { 14385e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_WOW_WAKEUP_HOST_EVENTID\n"); 14395e3dd157SKalle Valo } 14405e3dd157SKalle Valo 14415e3dd157SKalle Valo static void ath10k_wmi_event_dcs_interference(struct ath10k *ar, 14425e3dd157SKalle Valo struct sk_buff *skb) 14435e3dd157SKalle Valo { 14445e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_DCS_INTERFERENCE_EVENTID\n"); 14455e3dd157SKalle Valo } 14465e3dd157SKalle Valo 14475e3dd157SKalle Valo static void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, 14485e3dd157SKalle Valo struct sk_buff *skb) 14495e3dd157SKalle Valo { 14505e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_PDEV_TPC_CONFIG_EVENTID\n"); 14515e3dd157SKalle Valo } 14525e3dd157SKalle Valo 14535e3dd157SKalle Valo static void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, 14545e3dd157SKalle Valo struct sk_buff *skb) 14555e3dd157SKalle Valo { 14565e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_PDEV_FTM_INTG_EVENTID\n"); 14575e3dd157SKalle Valo } 14585e3dd157SKalle Valo 14595e3dd157SKalle Valo static void ath10k_wmi_event_gtk_offload_status(struct ath10k *ar, 14605e3dd157SKalle Valo struct sk_buff *skb) 14615e3dd157SKalle Valo { 14625e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_GTK_OFFLOAD_STATUS_EVENTID\n"); 14635e3dd157SKalle Valo } 14645e3dd157SKalle Valo 14655e3dd157SKalle Valo static void ath10k_wmi_event_gtk_rekey_fail(struct ath10k *ar, 14665e3dd157SKalle Valo struct sk_buff *skb) 14675e3dd157SKalle Valo { 14685e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_GTK_REKEY_FAIL_EVENTID\n"); 14695e3dd157SKalle Valo } 14705e3dd157SKalle Valo 14715e3dd157SKalle Valo static void ath10k_wmi_event_delba_complete(struct ath10k *ar, 14725e3dd157SKalle Valo struct sk_buff *skb) 14735e3dd157SKalle Valo { 14745e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_TX_DELBA_COMPLETE_EVENTID\n"); 14755e3dd157SKalle Valo } 14765e3dd157SKalle Valo 14775e3dd157SKalle Valo static void ath10k_wmi_event_addba_complete(struct ath10k *ar, 14785e3dd157SKalle Valo struct sk_buff *skb) 14795e3dd157SKalle Valo { 14805e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_TX_ADDBA_COMPLETE_EVENTID\n"); 14815e3dd157SKalle Valo } 14825e3dd157SKalle Valo 14835e3dd157SKalle Valo static void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar, 14845e3dd157SKalle Valo struct sk_buff *skb) 14855e3dd157SKalle Valo { 14865e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n"); 14875e3dd157SKalle Valo } 14885e3dd157SKalle Valo 14898a6618b0SBartosz Markowski static void ath10k_wmi_event_inst_rssi_stats(struct ath10k *ar, 14908a6618b0SBartosz Markowski struct sk_buff *skb) 14918a6618b0SBartosz Markowski { 14928a6618b0SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "WMI_INST_RSSI_STATS_EVENTID\n"); 14938a6618b0SBartosz Markowski } 14948a6618b0SBartosz Markowski 14958a6618b0SBartosz Markowski static void ath10k_wmi_event_vdev_standby_req(struct ath10k *ar, 14968a6618b0SBartosz Markowski struct sk_buff *skb) 14978a6618b0SBartosz Markowski { 14988a6618b0SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_STANDBY_REQ_EVENTID\n"); 14998a6618b0SBartosz Markowski } 15008a6618b0SBartosz Markowski 15018a6618b0SBartosz Markowski static void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar, 15028a6618b0SBartosz Markowski struct sk_buff *skb) 15038a6618b0SBartosz Markowski { 15048a6618b0SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_RESUME_REQ_EVENTID\n"); 15058a6618b0SBartosz Markowski } 15068a6618b0SBartosz Markowski 1507b3effe61SBartosz Markowski static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id, 1508b3effe61SBartosz Markowski u32 num_units, u32 unit_len) 1509b3effe61SBartosz Markowski { 1510b3effe61SBartosz Markowski dma_addr_t paddr; 1511b3effe61SBartosz Markowski u32 pool_size; 1512b3effe61SBartosz Markowski int idx = ar->wmi.num_mem_chunks; 1513b3effe61SBartosz Markowski 1514b3effe61SBartosz Markowski pool_size = num_units * round_up(unit_len, 4); 1515b3effe61SBartosz Markowski 1516b3effe61SBartosz Markowski if (!pool_size) 1517b3effe61SBartosz Markowski return -EINVAL; 1518b3effe61SBartosz Markowski 1519b3effe61SBartosz Markowski ar->wmi.mem_chunks[idx].vaddr = dma_alloc_coherent(ar->dev, 1520b3effe61SBartosz Markowski pool_size, 1521b3effe61SBartosz Markowski &paddr, 1522b3effe61SBartosz Markowski GFP_ATOMIC); 1523b3effe61SBartosz Markowski if (!ar->wmi.mem_chunks[idx].vaddr) { 1524b3effe61SBartosz Markowski ath10k_warn("failed to allocate memory chunk\n"); 1525b3effe61SBartosz Markowski return -ENOMEM; 1526b3effe61SBartosz Markowski } 1527b3effe61SBartosz Markowski 1528b3effe61SBartosz Markowski memset(ar->wmi.mem_chunks[idx].vaddr, 0, pool_size); 1529b3effe61SBartosz Markowski 1530b3effe61SBartosz Markowski ar->wmi.mem_chunks[idx].paddr = paddr; 1531b3effe61SBartosz Markowski ar->wmi.mem_chunks[idx].len = pool_size; 1532b3effe61SBartosz Markowski ar->wmi.mem_chunks[idx].req_id = req_id; 1533b3effe61SBartosz Markowski ar->wmi.num_mem_chunks++; 1534b3effe61SBartosz Markowski 1535b3effe61SBartosz Markowski return 0; 1536b3effe61SBartosz Markowski } 1537b3effe61SBartosz Markowski 15385e3dd157SKalle Valo static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, 15395e3dd157SKalle Valo struct sk_buff *skb) 15405e3dd157SKalle Valo { 15415e3dd157SKalle Valo struct wmi_service_ready_event *ev = (void *)skb->data; 15425e3dd157SKalle Valo 15435e3dd157SKalle Valo if (skb->len < sizeof(*ev)) { 15445e3dd157SKalle Valo ath10k_warn("Service ready event was %d B but expected %zu B. Wrong firmware version?\n", 15455e3dd157SKalle Valo skb->len, sizeof(*ev)); 15465e3dd157SKalle Valo return; 15475e3dd157SKalle Valo } 15485e3dd157SKalle Valo 15495e3dd157SKalle Valo ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power); 15505e3dd157SKalle Valo ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power); 15515e3dd157SKalle Valo ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info); 15525e3dd157SKalle Valo ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info); 15535e3dd157SKalle Valo ar->fw_version_major = 15545e3dd157SKalle Valo (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24; 15555e3dd157SKalle Valo ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff); 15565e3dd157SKalle Valo ar->fw_version_release = 15575e3dd157SKalle Valo (__le32_to_cpu(ev->sw_version_1) & 0xffff0000) >> 16; 15585e3dd157SKalle Valo ar->fw_version_build = (__le32_to_cpu(ev->sw_version_1) & 0x0000ffff); 15595e3dd157SKalle Valo ar->phy_capability = __le32_to_cpu(ev->phy_capability); 15608865bee4SMichal Kazior ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); 15618865bee4SMichal Kazior 15621a222435SKalle Valo /* only manually set fw features when not using FW IE format */ 15631a222435SKalle Valo if (ar->fw_api == 1 && ar->fw_version_build > 636) 15640d9b0438SMichal Kazior set_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features); 15650d9b0438SMichal Kazior 15668865bee4SMichal Kazior if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) { 15678865bee4SMichal Kazior ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n", 15688865bee4SMichal Kazior ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM); 15698865bee4SMichal Kazior ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM; 15708865bee4SMichal Kazior } 15715e3dd157SKalle Valo 15725e3dd157SKalle Valo ar->ath_common.regulatory.current_rd = 15735e3dd157SKalle Valo __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd); 15745e3dd157SKalle Valo 15755e3dd157SKalle Valo ath10k_debug_read_service_map(ar, ev->wmi_service_bitmap, 15765e3dd157SKalle Valo sizeof(ev->wmi_service_bitmap)); 15775e3dd157SKalle Valo 15785e3dd157SKalle Valo if (strlen(ar->hw->wiphy->fw_version) == 0) { 15795e3dd157SKalle Valo snprintf(ar->hw->wiphy->fw_version, 15805e3dd157SKalle Valo sizeof(ar->hw->wiphy->fw_version), 15815e3dd157SKalle Valo "%u.%u.%u.%u", 15825e3dd157SKalle Valo ar->fw_version_major, 15835e3dd157SKalle Valo ar->fw_version_minor, 15845e3dd157SKalle Valo ar->fw_version_release, 15855e3dd157SKalle Valo ar->fw_version_build); 15865e3dd157SKalle Valo } 15875e3dd157SKalle Valo 15885e3dd157SKalle Valo /* FIXME: it probably should be better to support this */ 15895e3dd157SKalle Valo if (__le32_to_cpu(ev->num_mem_reqs) > 0) { 15905e3dd157SKalle Valo ath10k_warn("target requested %d memory chunks; ignoring\n", 15915e3dd157SKalle Valo __le32_to_cpu(ev->num_mem_reqs)); 15925e3dd157SKalle Valo } 15935e3dd157SKalle Valo 15945e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 15958865bee4SMichal 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", 15965e3dd157SKalle Valo __le32_to_cpu(ev->sw_version), 15975e3dd157SKalle Valo __le32_to_cpu(ev->sw_version_1), 15985e3dd157SKalle Valo __le32_to_cpu(ev->abi_version), 15995e3dd157SKalle Valo __le32_to_cpu(ev->phy_capability), 16005e3dd157SKalle Valo __le32_to_cpu(ev->ht_cap_info), 16015e3dd157SKalle Valo __le32_to_cpu(ev->vht_cap_info), 16025e3dd157SKalle Valo __le32_to_cpu(ev->vht_supp_mcs), 16035e3dd157SKalle Valo __le32_to_cpu(ev->sys_cap_info), 16048865bee4SMichal Kazior __le32_to_cpu(ev->num_mem_reqs), 16058865bee4SMichal Kazior __le32_to_cpu(ev->num_rf_chains)); 16065e3dd157SKalle Valo 16075e3dd157SKalle Valo complete(&ar->wmi.service_ready); 16085e3dd157SKalle Valo } 16095e3dd157SKalle Valo 16106f97d256SBartosz Markowski static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar, 16116f97d256SBartosz Markowski struct sk_buff *skb) 16126f97d256SBartosz Markowski { 1613b3effe61SBartosz Markowski u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i; 1614b3effe61SBartosz Markowski int ret; 16156f97d256SBartosz Markowski struct wmi_service_ready_event_10x *ev = (void *)skb->data; 16166f97d256SBartosz Markowski 16176f97d256SBartosz Markowski if (skb->len < sizeof(*ev)) { 16186f97d256SBartosz Markowski ath10k_warn("Service ready event was %d B but expected %zu B. Wrong firmware version?\n", 16196f97d256SBartosz Markowski skb->len, sizeof(*ev)); 16206f97d256SBartosz Markowski return; 16216f97d256SBartosz Markowski } 16226f97d256SBartosz Markowski 16236f97d256SBartosz Markowski ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power); 16246f97d256SBartosz Markowski ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power); 16256f97d256SBartosz Markowski ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info); 16266f97d256SBartosz Markowski ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info); 16276f97d256SBartosz Markowski ar->fw_version_major = 16286f97d256SBartosz Markowski (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24; 16296f97d256SBartosz Markowski ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff); 16306f97d256SBartosz Markowski ar->phy_capability = __le32_to_cpu(ev->phy_capability); 16316f97d256SBartosz Markowski ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); 16326f97d256SBartosz Markowski 16336f97d256SBartosz Markowski if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) { 16346f97d256SBartosz Markowski ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n", 16356f97d256SBartosz Markowski ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM); 16366f97d256SBartosz Markowski ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM; 16376f97d256SBartosz Markowski } 16386f97d256SBartosz Markowski 16396f97d256SBartosz Markowski ar->ath_common.regulatory.current_rd = 16406f97d256SBartosz Markowski __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd); 16416f97d256SBartosz Markowski 16426f97d256SBartosz Markowski ath10k_debug_read_service_map(ar, ev->wmi_service_bitmap, 16436f97d256SBartosz Markowski sizeof(ev->wmi_service_bitmap)); 16446f97d256SBartosz Markowski 16456f97d256SBartosz Markowski if (strlen(ar->hw->wiphy->fw_version) == 0) { 16466f97d256SBartosz Markowski snprintf(ar->hw->wiphy->fw_version, 16476f97d256SBartosz Markowski sizeof(ar->hw->wiphy->fw_version), 16486f97d256SBartosz Markowski "%u.%u", 16496f97d256SBartosz Markowski ar->fw_version_major, 16506f97d256SBartosz Markowski ar->fw_version_minor); 16516f97d256SBartosz Markowski } 16526f97d256SBartosz Markowski 1653b3effe61SBartosz Markowski num_mem_reqs = __le32_to_cpu(ev->num_mem_reqs); 1654b3effe61SBartosz Markowski 1655b3effe61SBartosz Markowski if (num_mem_reqs > ATH10K_MAX_MEM_REQS) { 1656b3effe61SBartosz Markowski ath10k_warn("requested memory chunks number (%d) exceeds the limit\n", 1657b3effe61SBartosz Markowski num_mem_reqs); 1658b3effe61SBartosz Markowski return; 16596f97d256SBartosz Markowski } 16606f97d256SBartosz Markowski 1661b3effe61SBartosz Markowski if (!num_mem_reqs) 1662b3effe61SBartosz Markowski goto exit; 1663b3effe61SBartosz Markowski 1664b3effe61SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "firmware has requested %d memory chunks\n", 1665b3effe61SBartosz Markowski num_mem_reqs); 1666b3effe61SBartosz Markowski 1667b3effe61SBartosz Markowski for (i = 0; i < num_mem_reqs; ++i) { 1668b3effe61SBartosz Markowski req_id = __le32_to_cpu(ev->mem_reqs[i].req_id); 1669b3effe61SBartosz Markowski num_units = __le32_to_cpu(ev->mem_reqs[i].num_units); 1670b3effe61SBartosz Markowski unit_size = __le32_to_cpu(ev->mem_reqs[i].unit_size); 1671b3effe61SBartosz Markowski num_unit_info = __le32_to_cpu(ev->mem_reqs[i].num_unit_info); 1672b3effe61SBartosz Markowski 1673b3effe61SBartosz Markowski if (num_unit_info & NUM_UNITS_IS_NUM_PEERS) 1674b3effe61SBartosz Markowski /* number of units to allocate is number of 1675b3effe61SBartosz Markowski * peers, 1 extra for self peer on target */ 1676b3effe61SBartosz Markowski /* this needs to be tied, host and target 1677b3effe61SBartosz Markowski * can get out of sync */ 1678ec6a73f0SBartosz Markowski num_units = TARGET_10X_NUM_PEERS + 1; 1679b3effe61SBartosz Markowski else if (num_unit_info & NUM_UNITS_IS_NUM_VDEVS) 1680ec6a73f0SBartosz Markowski num_units = TARGET_10X_NUM_VDEVS + 1; 1681b3effe61SBartosz Markowski 1682b3effe61SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, 1683b3effe61SBartosz Markowski "wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n", 1684b3effe61SBartosz Markowski req_id, 1685b3effe61SBartosz Markowski __le32_to_cpu(ev->mem_reqs[i].num_units), 1686b3effe61SBartosz Markowski num_unit_info, 1687b3effe61SBartosz Markowski unit_size, 1688b3effe61SBartosz Markowski num_units); 1689b3effe61SBartosz Markowski 1690b3effe61SBartosz Markowski ret = ath10k_wmi_alloc_host_mem(ar, req_id, num_units, 1691b3effe61SBartosz Markowski unit_size); 1692b3effe61SBartosz Markowski if (ret) 1693b3effe61SBartosz Markowski return; 1694b3effe61SBartosz Markowski } 1695b3effe61SBartosz Markowski 1696b3effe61SBartosz Markowski exit: 16976f97d256SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, 16986f97d256SBartosz 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", 16996f97d256SBartosz Markowski __le32_to_cpu(ev->sw_version), 17006f97d256SBartosz Markowski __le32_to_cpu(ev->abi_version), 17016f97d256SBartosz Markowski __le32_to_cpu(ev->phy_capability), 17026f97d256SBartosz Markowski __le32_to_cpu(ev->ht_cap_info), 17036f97d256SBartosz Markowski __le32_to_cpu(ev->vht_cap_info), 17046f97d256SBartosz Markowski __le32_to_cpu(ev->vht_supp_mcs), 17056f97d256SBartosz Markowski __le32_to_cpu(ev->sys_cap_info), 17066f97d256SBartosz Markowski __le32_to_cpu(ev->num_mem_reqs), 17076f97d256SBartosz Markowski __le32_to_cpu(ev->num_rf_chains)); 17086f97d256SBartosz Markowski 17096f97d256SBartosz Markowski complete(&ar->wmi.service_ready); 17106f97d256SBartosz Markowski } 17116f97d256SBartosz Markowski 17125e3dd157SKalle Valo static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) 17135e3dd157SKalle Valo { 17145e3dd157SKalle Valo struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data; 17155e3dd157SKalle Valo 17165e3dd157SKalle Valo if (WARN_ON(skb->len < sizeof(*ev))) 17175e3dd157SKalle Valo return -EINVAL; 17185e3dd157SKalle Valo 17195e3dd157SKalle Valo memcpy(ar->mac_addr, ev->mac_addr.addr, ETH_ALEN); 17205e3dd157SKalle Valo 17215e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 17225e3dd157SKalle Valo "wmi event ready sw_version %u abi_version %u mac_addr %pM status %d\n", 17235e3dd157SKalle Valo __le32_to_cpu(ev->sw_version), 17245e3dd157SKalle Valo __le32_to_cpu(ev->abi_version), 17255e3dd157SKalle Valo ev->mac_addr.addr, 17265e3dd157SKalle Valo __le32_to_cpu(ev->status)); 17275e3dd157SKalle Valo 17285e3dd157SKalle Valo complete(&ar->wmi.unified_ready); 17295e3dd157SKalle Valo return 0; 17305e3dd157SKalle Valo } 17315e3dd157SKalle Valo 1732ce42870eSBartosz Markowski static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb) 17335e3dd157SKalle Valo { 17345e3dd157SKalle Valo struct wmi_cmd_hdr *cmd_hdr; 17355e3dd157SKalle Valo enum wmi_event_id id; 17365e3dd157SKalle Valo u16 len; 17375e3dd157SKalle Valo 17385e3dd157SKalle Valo cmd_hdr = (struct wmi_cmd_hdr *)skb->data; 17395e3dd157SKalle Valo id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); 17405e3dd157SKalle Valo 17415e3dd157SKalle Valo if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) 17425e3dd157SKalle Valo return; 17435e3dd157SKalle Valo 17445e3dd157SKalle Valo len = skb->len; 17455e3dd157SKalle Valo 17465e3dd157SKalle Valo trace_ath10k_wmi_event(id, skb->data, skb->len); 17475e3dd157SKalle Valo 17485e3dd157SKalle Valo switch (id) { 17495e3dd157SKalle Valo case WMI_MGMT_RX_EVENTID: 17505e3dd157SKalle Valo ath10k_wmi_event_mgmt_rx(ar, skb); 17515e3dd157SKalle Valo /* mgmt_rx() owns the skb now! */ 17525e3dd157SKalle Valo return; 17535e3dd157SKalle Valo case WMI_SCAN_EVENTID: 17545e3dd157SKalle Valo ath10k_wmi_event_scan(ar, skb); 17555e3dd157SKalle Valo break; 17565e3dd157SKalle Valo case WMI_CHAN_INFO_EVENTID: 17575e3dd157SKalle Valo ath10k_wmi_event_chan_info(ar, skb); 17585e3dd157SKalle Valo break; 17595e3dd157SKalle Valo case WMI_ECHO_EVENTID: 17605e3dd157SKalle Valo ath10k_wmi_event_echo(ar, skb); 17615e3dd157SKalle Valo break; 17625e3dd157SKalle Valo case WMI_DEBUG_MESG_EVENTID: 17635e3dd157SKalle Valo ath10k_wmi_event_debug_mesg(ar, skb); 17645e3dd157SKalle Valo break; 17655e3dd157SKalle Valo case WMI_UPDATE_STATS_EVENTID: 17665e3dd157SKalle Valo ath10k_wmi_event_update_stats(ar, skb); 17675e3dd157SKalle Valo break; 17685e3dd157SKalle Valo case WMI_VDEV_START_RESP_EVENTID: 17695e3dd157SKalle Valo ath10k_wmi_event_vdev_start_resp(ar, skb); 17705e3dd157SKalle Valo break; 17715e3dd157SKalle Valo case WMI_VDEV_STOPPED_EVENTID: 17725e3dd157SKalle Valo ath10k_wmi_event_vdev_stopped(ar, skb); 17735e3dd157SKalle Valo break; 17745e3dd157SKalle Valo case WMI_PEER_STA_KICKOUT_EVENTID: 17755e3dd157SKalle Valo ath10k_wmi_event_peer_sta_kickout(ar, skb); 17765e3dd157SKalle Valo break; 17775e3dd157SKalle Valo case WMI_HOST_SWBA_EVENTID: 17785e3dd157SKalle Valo ath10k_wmi_event_host_swba(ar, skb); 17795e3dd157SKalle Valo break; 17805e3dd157SKalle Valo case WMI_TBTTOFFSET_UPDATE_EVENTID: 17815e3dd157SKalle Valo ath10k_wmi_event_tbttoffset_update(ar, skb); 17825e3dd157SKalle Valo break; 17835e3dd157SKalle Valo case WMI_PHYERR_EVENTID: 17845e3dd157SKalle Valo ath10k_wmi_event_phyerr(ar, skb); 17855e3dd157SKalle Valo break; 17865e3dd157SKalle Valo case WMI_ROAM_EVENTID: 17875e3dd157SKalle Valo ath10k_wmi_event_roam(ar, skb); 17885e3dd157SKalle Valo break; 17895e3dd157SKalle Valo case WMI_PROFILE_MATCH: 17905e3dd157SKalle Valo ath10k_wmi_event_profile_match(ar, skb); 17915e3dd157SKalle Valo break; 17925e3dd157SKalle Valo case WMI_DEBUG_PRINT_EVENTID: 17935e3dd157SKalle Valo ath10k_wmi_event_debug_print(ar, skb); 17945e3dd157SKalle Valo break; 17955e3dd157SKalle Valo case WMI_PDEV_QVIT_EVENTID: 17965e3dd157SKalle Valo ath10k_wmi_event_pdev_qvit(ar, skb); 17975e3dd157SKalle Valo break; 17985e3dd157SKalle Valo case WMI_WLAN_PROFILE_DATA_EVENTID: 17995e3dd157SKalle Valo ath10k_wmi_event_wlan_profile_data(ar, skb); 18005e3dd157SKalle Valo break; 18015e3dd157SKalle Valo case WMI_RTT_MEASUREMENT_REPORT_EVENTID: 18025e3dd157SKalle Valo ath10k_wmi_event_rtt_measurement_report(ar, skb); 18035e3dd157SKalle Valo break; 18045e3dd157SKalle Valo case WMI_TSF_MEASUREMENT_REPORT_EVENTID: 18055e3dd157SKalle Valo ath10k_wmi_event_tsf_measurement_report(ar, skb); 18065e3dd157SKalle Valo break; 18075e3dd157SKalle Valo case WMI_RTT_ERROR_REPORT_EVENTID: 18085e3dd157SKalle Valo ath10k_wmi_event_rtt_error_report(ar, skb); 18095e3dd157SKalle Valo break; 18105e3dd157SKalle Valo case WMI_WOW_WAKEUP_HOST_EVENTID: 18115e3dd157SKalle Valo ath10k_wmi_event_wow_wakeup_host(ar, skb); 18125e3dd157SKalle Valo break; 18135e3dd157SKalle Valo case WMI_DCS_INTERFERENCE_EVENTID: 18145e3dd157SKalle Valo ath10k_wmi_event_dcs_interference(ar, skb); 18155e3dd157SKalle Valo break; 18165e3dd157SKalle Valo case WMI_PDEV_TPC_CONFIG_EVENTID: 18175e3dd157SKalle Valo ath10k_wmi_event_pdev_tpc_config(ar, skb); 18185e3dd157SKalle Valo break; 18195e3dd157SKalle Valo case WMI_PDEV_FTM_INTG_EVENTID: 18205e3dd157SKalle Valo ath10k_wmi_event_pdev_ftm_intg(ar, skb); 18215e3dd157SKalle Valo break; 18225e3dd157SKalle Valo case WMI_GTK_OFFLOAD_STATUS_EVENTID: 18235e3dd157SKalle Valo ath10k_wmi_event_gtk_offload_status(ar, skb); 18245e3dd157SKalle Valo break; 18255e3dd157SKalle Valo case WMI_GTK_REKEY_FAIL_EVENTID: 18265e3dd157SKalle Valo ath10k_wmi_event_gtk_rekey_fail(ar, skb); 18275e3dd157SKalle Valo break; 18285e3dd157SKalle Valo case WMI_TX_DELBA_COMPLETE_EVENTID: 18295e3dd157SKalle Valo ath10k_wmi_event_delba_complete(ar, skb); 18305e3dd157SKalle Valo break; 18315e3dd157SKalle Valo case WMI_TX_ADDBA_COMPLETE_EVENTID: 18325e3dd157SKalle Valo ath10k_wmi_event_addba_complete(ar, skb); 18335e3dd157SKalle Valo break; 18345e3dd157SKalle Valo case WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID: 18355e3dd157SKalle Valo ath10k_wmi_event_vdev_install_key_complete(ar, skb); 18365e3dd157SKalle Valo break; 18375e3dd157SKalle Valo case WMI_SERVICE_READY_EVENTID: 18385e3dd157SKalle Valo ath10k_wmi_service_ready_event_rx(ar, skb); 18395e3dd157SKalle Valo break; 18405e3dd157SKalle Valo case WMI_READY_EVENTID: 18415e3dd157SKalle Valo ath10k_wmi_ready_event_rx(ar, skb); 18425e3dd157SKalle Valo break; 18435e3dd157SKalle Valo default: 18445e3dd157SKalle Valo ath10k_warn("Unknown eventid: %d\n", id); 18455e3dd157SKalle Valo break; 18465e3dd157SKalle Valo } 18475e3dd157SKalle Valo 18485e3dd157SKalle Valo dev_kfree_skb(skb); 18495e3dd157SKalle Valo } 18505e3dd157SKalle Valo 18518a6618b0SBartosz Markowski static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) 18528a6618b0SBartosz Markowski { 18538a6618b0SBartosz Markowski struct wmi_cmd_hdr *cmd_hdr; 18548a6618b0SBartosz Markowski enum wmi_10x_event_id id; 18558a6618b0SBartosz Markowski u16 len; 18568a6618b0SBartosz Markowski 18578a6618b0SBartosz Markowski cmd_hdr = (struct wmi_cmd_hdr *)skb->data; 18588a6618b0SBartosz Markowski id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); 18598a6618b0SBartosz Markowski 18608a6618b0SBartosz Markowski if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) 18618a6618b0SBartosz Markowski return; 18628a6618b0SBartosz Markowski 18638a6618b0SBartosz Markowski len = skb->len; 18648a6618b0SBartosz Markowski 18658a6618b0SBartosz Markowski trace_ath10k_wmi_event(id, skb->data, skb->len); 18668a6618b0SBartosz Markowski 18678a6618b0SBartosz Markowski switch (id) { 18688a6618b0SBartosz Markowski case WMI_10X_MGMT_RX_EVENTID: 18698a6618b0SBartosz Markowski ath10k_wmi_event_mgmt_rx(ar, skb); 18708a6618b0SBartosz Markowski /* mgmt_rx() owns the skb now! */ 18718a6618b0SBartosz Markowski return; 18728a6618b0SBartosz Markowski case WMI_10X_SCAN_EVENTID: 18738a6618b0SBartosz Markowski ath10k_wmi_event_scan(ar, skb); 18748a6618b0SBartosz Markowski break; 18758a6618b0SBartosz Markowski case WMI_10X_CHAN_INFO_EVENTID: 18768a6618b0SBartosz Markowski ath10k_wmi_event_chan_info(ar, skb); 18778a6618b0SBartosz Markowski break; 18788a6618b0SBartosz Markowski case WMI_10X_ECHO_EVENTID: 18798a6618b0SBartosz Markowski ath10k_wmi_event_echo(ar, skb); 18808a6618b0SBartosz Markowski break; 18818a6618b0SBartosz Markowski case WMI_10X_DEBUG_MESG_EVENTID: 18828a6618b0SBartosz Markowski ath10k_wmi_event_debug_mesg(ar, skb); 18838a6618b0SBartosz Markowski break; 18848a6618b0SBartosz Markowski case WMI_10X_UPDATE_STATS_EVENTID: 18858a6618b0SBartosz Markowski ath10k_wmi_event_update_stats(ar, skb); 18868a6618b0SBartosz Markowski break; 18878a6618b0SBartosz Markowski case WMI_10X_VDEV_START_RESP_EVENTID: 18888a6618b0SBartosz Markowski ath10k_wmi_event_vdev_start_resp(ar, skb); 18898a6618b0SBartosz Markowski break; 18908a6618b0SBartosz Markowski case WMI_10X_VDEV_STOPPED_EVENTID: 18918a6618b0SBartosz Markowski ath10k_wmi_event_vdev_stopped(ar, skb); 18928a6618b0SBartosz Markowski break; 18938a6618b0SBartosz Markowski case WMI_10X_PEER_STA_KICKOUT_EVENTID: 18948a6618b0SBartosz Markowski ath10k_wmi_event_peer_sta_kickout(ar, skb); 18958a6618b0SBartosz Markowski break; 18968a6618b0SBartosz Markowski case WMI_10X_HOST_SWBA_EVENTID: 18978a6618b0SBartosz Markowski ath10k_wmi_event_host_swba(ar, skb); 18988a6618b0SBartosz Markowski break; 18998a6618b0SBartosz Markowski case WMI_10X_TBTTOFFSET_UPDATE_EVENTID: 19008a6618b0SBartosz Markowski ath10k_wmi_event_tbttoffset_update(ar, skb); 19018a6618b0SBartosz Markowski break; 19028a6618b0SBartosz Markowski case WMI_10X_PHYERR_EVENTID: 19038a6618b0SBartosz Markowski ath10k_wmi_event_phyerr(ar, skb); 19048a6618b0SBartosz Markowski break; 19058a6618b0SBartosz Markowski case WMI_10X_ROAM_EVENTID: 19068a6618b0SBartosz Markowski ath10k_wmi_event_roam(ar, skb); 19078a6618b0SBartosz Markowski break; 19088a6618b0SBartosz Markowski case WMI_10X_PROFILE_MATCH: 19098a6618b0SBartosz Markowski ath10k_wmi_event_profile_match(ar, skb); 19108a6618b0SBartosz Markowski break; 19118a6618b0SBartosz Markowski case WMI_10X_DEBUG_PRINT_EVENTID: 19128a6618b0SBartosz Markowski ath10k_wmi_event_debug_print(ar, skb); 19138a6618b0SBartosz Markowski break; 19148a6618b0SBartosz Markowski case WMI_10X_PDEV_QVIT_EVENTID: 19158a6618b0SBartosz Markowski ath10k_wmi_event_pdev_qvit(ar, skb); 19168a6618b0SBartosz Markowski break; 19178a6618b0SBartosz Markowski case WMI_10X_WLAN_PROFILE_DATA_EVENTID: 19188a6618b0SBartosz Markowski ath10k_wmi_event_wlan_profile_data(ar, skb); 19198a6618b0SBartosz Markowski break; 19208a6618b0SBartosz Markowski case WMI_10X_RTT_MEASUREMENT_REPORT_EVENTID: 19218a6618b0SBartosz Markowski ath10k_wmi_event_rtt_measurement_report(ar, skb); 19228a6618b0SBartosz Markowski break; 19238a6618b0SBartosz Markowski case WMI_10X_TSF_MEASUREMENT_REPORT_EVENTID: 19248a6618b0SBartosz Markowski ath10k_wmi_event_tsf_measurement_report(ar, skb); 19258a6618b0SBartosz Markowski break; 19268a6618b0SBartosz Markowski case WMI_10X_RTT_ERROR_REPORT_EVENTID: 19278a6618b0SBartosz Markowski ath10k_wmi_event_rtt_error_report(ar, skb); 19288a6618b0SBartosz Markowski break; 19298a6618b0SBartosz Markowski case WMI_10X_WOW_WAKEUP_HOST_EVENTID: 19308a6618b0SBartosz Markowski ath10k_wmi_event_wow_wakeup_host(ar, skb); 19318a6618b0SBartosz Markowski break; 19328a6618b0SBartosz Markowski case WMI_10X_DCS_INTERFERENCE_EVENTID: 19338a6618b0SBartosz Markowski ath10k_wmi_event_dcs_interference(ar, skb); 19348a6618b0SBartosz Markowski break; 19358a6618b0SBartosz Markowski case WMI_10X_PDEV_TPC_CONFIG_EVENTID: 19368a6618b0SBartosz Markowski ath10k_wmi_event_pdev_tpc_config(ar, skb); 19378a6618b0SBartosz Markowski break; 19388a6618b0SBartosz Markowski case WMI_10X_INST_RSSI_STATS_EVENTID: 19398a6618b0SBartosz Markowski ath10k_wmi_event_inst_rssi_stats(ar, skb); 19408a6618b0SBartosz Markowski break; 19418a6618b0SBartosz Markowski case WMI_10X_VDEV_STANDBY_REQ_EVENTID: 19428a6618b0SBartosz Markowski ath10k_wmi_event_vdev_standby_req(ar, skb); 19438a6618b0SBartosz Markowski break; 19448a6618b0SBartosz Markowski case WMI_10X_VDEV_RESUME_REQ_EVENTID: 19458a6618b0SBartosz Markowski ath10k_wmi_event_vdev_resume_req(ar, skb); 19468a6618b0SBartosz Markowski break; 19478a6618b0SBartosz Markowski case WMI_10X_SERVICE_READY_EVENTID: 19486f97d256SBartosz Markowski ath10k_wmi_10x_service_ready_event_rx(ar, skb); 19498a6618b0SBartosz Markowski break; 19508a6618b0SBartosz Markowski case WMI_10X_READY_EVENTID: 19518a6618b0SBartosz Markowski ath10k_wmi_ready_event_rx(ar, skb); 19528a6618b0SBartosz Markowski break; 19538a6618b0SBartosz Markowski default: 19548a6618b0SBartosz Markowski ath10k_warn("Unknown eventid: %d\n", id); 19558a6618b0SBartosz Markowski break; 19568a6618b0SBartosz Markowski } 19578a6618b0SBartosz Markowski 19588a6618b0SBartosz Markowski dev_kfree_skb(skb); 19598a6618b0SBartosz Markowski } 19608a6618b0SBartosz Markowski 19618a6618b0SBartosz Markowski 1962ce42870eSBartosz Markowski static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb) 1963ce42870eSBartosz Markowski { 1964ce42870eSBartosz Markowski if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) 19658a6618b0SBartosz Markowski ath10k_wmi_10x_process_rx(ar, skb); 1966ce42870eSBartosz Markowski else 1967ce42870eSBartosz Markowski ath10k_wmi_main_process_rx(ar, skb); 1968ce42870eSBartosz Markowski } 1969ce42870eSBartosz Markowski 19705e3dd157SKalle Valo /* WMI Initialization functions */ 19715e3dd157SKalle Valo int ath10k_wmi_attach(struct ath10k *ar) 19725e3dd157SKalle Valo { 1973ce42870eSBartosz Markowski if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { 1974b7e3adf9SBartosz Markowski ar->wmi.cmd = &wmi_10x_cmd_map; 19756d1506e7SBartosz Markowski ar->wmi.vdev_param = &wmi_10x_vdev_param_map; 1976226a339bSBartosz Markowski ar->wmi.pdev_param = &wmi_10x_pdev_param_map; 1977ce42870eSBartosz Markowski } else { 1978ce42870eSBartosz Markowski ar->wmi.cmd = &wmi_cmd_map; 19796d1506e7SBartosz Markowski ar->wmi.vdev_param = &wmi_vdev_param_map; 1980226a339bSBartosz Markowski ar->wmi.pdev_param = &wmi_pdev_param_map; 1981ce42870eSBartosz Markowski } 1982ce42870eSBartosz Markowski 19835e3dd157SKalle Valo init_completion(&ar->wmi.service_ready); 19845e3dd157SKalle Valo init_completion(&ar->wmi.unified_ready); 1985be8b3943SMichal Kazior init_waitqueue_head(&ar->wmi.tx_credits_wq); 19865e3dd157SKalle Valo 19878acd3c97SBartosz Markowski return 0; 19885e3dd157SKalle Valo } 19895e3dd157SKalle Valo 19905e3dd157SKalle Valo void ath10k_wmi_detach(struct ath10k *ar) 19915e3dd157SKalle Valo { 1992b3effe61SBartosz Markowski int i; 1993b3effe61SBartosz Markowski 1994b3effe61SBartosz Markowski /* free the host memory chunks requested by firmware */ 1995b3effe61SBartosz Markowski for (i = 0; i < ar->wmi.num_mem_chunks; i++) { 1996b3effe61SBartosz Markowski dma_free_coherent(ar->dev, 1997b3effe61SBartosz Markowski ar->wmi.mem_chunks[i].len, 1998b3effe61SBartosz Markowski ar->wmi.mem_chunks[i].vaddr, 1999b3effe61SBartosz Markowski ar->wmi.mem_chunks[i].paddr); 2000b3effe61SBartosz Markowski } 2001b3effe61SBartosz Markowski 2002b3effe61SBartosz Markowski ar->wmi.num_mem_chunks = 0; 20035e3dd157SKalle Valo } 20045e3dd157SKalle Valo 20055e3dd157SKalle Valo int ath10k_wmi_connect_htc_service(struct ath10k *ar) 20065e3dd157SKalle Valo { 20075e3dd157SKalle Valo int status; 20085e3dd157SKalle Valo struct ath10k_htc_svc_conn_req conn_req; 20095e3dd157SKalle Valo struct ath10k_htc_svc_conn_resp conn_resp; 20105e3dd157SKalle Valo 20115e3dd157SKalle Valo memset(&conn_req, 0, sizeof(conn_req)); 20125e3dd157SKalle Valo memset(&conn_resp, 0, sizeof(conn_resp)); 20135e3dd157SKalle Valo 20145e3dd157SKalle Valo /* these fields are the same for all service endpoints */ 20155e3dd157SKalle Valo conn_req.ep_ops.ep_tx_complete = ath10k_wmi_htc_tx_complete; 20165e3dd157SKalle Valo conn_req.ep_ops.ep_rx_complete = ath10k_wmi_process_rx; 2017be8b3943SMichal Kazior conn_req.ep_ops.ep_tx_credits = ath10k_wmi_op_ep_tx_credits; 20185e3dd157SKalle Valo 20195e3dd157SKalle Valo /* connect to control service */ 20205e3dd157SKalle Valo conn_req.service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL; 20215e3dd157SKalle Valo 2022cd003fadSMichal Kazior status = ath10k_htc_connect_service(&ar->htc, &conn_req, &conn_resp); 20235e3dd157SKalle Valo if (status) { 20245e3dd157SKalle Valo ath10k_warn("failed to connect to WMI CONTROL service status: %d\n", 20255e3dd157SKalle Valo status); 20265e3dd157SKalle Valo return status; 20275e3dd157SKalle Valo } 20285e3dd157SKalle Valo 20295e3dd157SKalle Valo ar->wmi.eid = conn_resp.eid; 20305e3dd157SKalle Valo return 0; 20315e3dd157SKalle Valo } 20325e3dd157SKalle Valo 20335e3dd157SKalle Valo int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, 20345e3dd157SKalle Valo u16 rd5g, u16 ctl2g, u16 ctl5g) 20355e3dd157SKalle Valo { 20365e3dd157SKalle Valo struct wmi_pdev_set_regdomain_cmd *cmd; 20375e3dd157SKalle Valo struct sk_buff *skb; 20385e3dd157SKalle Valo 20395e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 20405e3dd157SKalle Valo if (!skb) 20415e3dd157SKalle Valo return -ENOMEM; 20425e3dd157SKalle Valo 20435e3dd157SKalle Valo cmd = (struct wmi_pdev_set_regdomain_cmd *)skb->data; 20445e3dd157SKalle Valo cmd->reg_domain = __cpu_to_le32(rd); 20455e3dd157SKalle Valo cmd->reg_domain_2G = __cpu_to_le32(rd2g); 20465e3dd157SKalle Valo cmd->reg_domain_5G = __cpu_to_le32(rd5g); 20475e3dd157SKalle Valo cmd->conformance_test_limit_2G = __cpu_to_le32(ctl2g); 20485e3dd157SKalle Valo cmd->conformance_test_limit_5G = __cpu_to_le32(ctl5g); 20495e3dd157SKalle Valo 20505e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 20515e3dd157SKalle Valo "wmi pdev regdomain rd %x rd2g %x rd5g %x ctl2g %x ctl5g %x\n", 20525e3dd157SKalle Valo rd, rd2g, rd5g, ctl2g, ctl5g); 20535e3dd157SKalle Valo 2054ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, 2055ce42870eSBartosz Markowski ar->wmi.cmd->pdev_set_regdomain_cmdid); 20565e3dd157SKalle Valo } 20575e3dd157SKalle Valo 20585e3dd157SKalle Valo int ath10k_wmi_pdev_set_channel(struct ath10k *ar, 20595e3dd157SKalle Valo const struct wmi_channel_arg *arg) 20605e3dd157SKalle Valo { 20615e3dd157SKalle Valo struct wmi_set_channel_cmd *cmd; 20625e3dd157SKalle Valo struct sk_buff *skb; 20635e3dd157SKalle Valo 20645e3dd157SKalle Valo if (arg->passive) 20655e3dd157SKalle Valo return -EINVAL; 20665e3dd157SKalle Valo 20675e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 20685e3dd157SKalle Valo if (!skb) 20695e3dd157SKalle Valo return -ENOMEM; 20705e3dd157SKalle Valo 20715e3dd157SKalle Valo cmd = (struct wmi_set_channel_cmd *)skb->data; 20725e3dd157SKalle Valo cmd->chan.mhz = __cpu_to_le32(arg->freq); 20735e3dd157SKalle Valo cmd->chan.band_center_freq1 = __cpu_to_le32(arg->freq); 20745e3dd157SKalle Valo cmd->chan.mode = arg->mode; 20755e3dd157SKalle Valo cmd->chan.min_power = arg->min_power; 20765e3dd157SKalle Valo cmd->chan.max_power = arg->max_power; 20775e3dd157SKalle Valo cmd->chan.reg_power = arg->max_reg_power; 20785e3dd157SKalle Valo cmd->chan.reg_classid = arg->reg_class_id; 20795e3dd157SKalle Valo cmd->chan.antenna_max = arg->max_antenna_gain; 20805e3dd157SKalle Valo 20815e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 20825e3dd157SKalle Valo "wmi set channel mode %d freq %d\n", 20835e3dd157SKalle Valo arg->mode, arg->freq); 20845e3dd157SKalle Valo 2085ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, 2086ce42870eSBartosz Markowski ar->wmi.cmd->pdev_set_channel_cmdid); 20875e3dd157SKalle Valo } 20885e3dd157SKalle Valo 20895e3dd157SKalle Valo int ath10k_wmi_pdev_suspend_target(struct ath10k *ar) 20905e3dd157SKalle Valo { 20915e3dd157SKalle Valo struct wmi_pdev_suspend_cmd *cmd; 20925e3dd157SKalle Valo struct sk_buff *skb; 20935e3dd157SKalle Valo 20945e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 20955e3dd157SKalle Valo if (!skb) 20965e3dd157SKalle Valo return -ENOMEM; 20975e3dd157SKalle Valo 20985e3dd157SKalle Valo cmd = (struct wmi_pdev_suspend_cmd *)skb->data; 20995e3dd157SKalle Valo cmd->suspend_opt = WMI_PDEV_SUSPEND; 21005e3dd157SKalle Valo 2101ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_suspend_cmdid); 21025e3dd157SKalle Valo } 21035e3dd157SKalle Valo 21045e3dd157SKalle Valo int ath10k_wmi_pdev_resume_target(struct ath10k *ar) 21055e3dd157SKalle Valo { 21065e3dd157SKalle Valo struct sk_buff *skb; 21075e3dd157SKalle Valo 21085e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(0); 21095e3dd157SKalle Valo if (skb == NULL) 21105e3dd157SKalle Valo return -ENOMEM; 21115e3dd157SKalle Valo 2112ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_resume_cmdid); 21135e3dd157SKalle Valo } 21145e3dd157SKalle Valo 2115226a339bSBartosz Markowski int ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value) 21165e3dd157SKalle Valo { 21175e3dd157SKalle Valo struct wmi_pdev_set_param_cmd *cmd; 21185e3dd157SKalle Valo struct sk_buff *skb; 21195e3dd157SKalle Valo 2120226a339bSBartosz Markowski if (id == WMI_PDEV_PARAM_UNSUPPORTED) { 2121226a339bSBartosz Markowski ath10k_warn("pdev param %d not supported by firmware\n", id); 2122d544943aSBartosz Markowski return -EOPNOTSUPP; 2123226a339bSBartosz Markowski } 2124226a339bSBartosz Markowski 21255e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 21265e3dd157SKalle Valo if (!skb) 21275e3dd157SKalle Valo return -ENOMEM; 21285e3dd157SKalle Valo 21295e3dd157SKalle Valo cmd = (struct wmi_pdev_set_param_cmd *)skb->data; 21305e3dd157SKalle Valo cmd->param_id = __cpu_to_le32(id); 21315e3dd157SKalle Valo cmd->param_value = __cpu_to_le32(value); 21325e3dd157SKalle Valo 21335e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set param %d value %d\n", 21345e3dd157SKalle Valo id, value); 2135ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid); 21365e3dd157SKalle Valo } 21375e3dd157SKalle Valo 213812b2b9e3SBartosz Markowski static int ath10k_wmi_main_cmd_init(struct ath10k *ar) 21395e3dd157SKalle Valo { 21405e3dd157SKalle Valo struct wmi_init_cmd *cmd; 21415e3dd157SKalle Valo struct sk_buff *buf; 21425e3dd157SKalle Valo struct wmi_resource_config config = {}; 2143b3effe61SBartosz Markowski u32 len, val; 2144b3effe61SBartosz Markowski int i; 21455e3dd157SKalle Valo 21465e3dd157SKalle Valo config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS); 21475e3dd157SKalle Valo config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS); 21485e3dd157SKalle Valo config.num_offload_peers = __cpu_to_le32(TARGET_NUM_OFFLOAD_PEERS); 21495e3dd157SKalle Valo 21505e3dd157SKalle Valo config.num_offload_reorder_bufs = 21515e3dd157SKalle Valo __cpu_to_le32(TARGET_NUM_OFFLOAD_REORDER_BUFS); 21525e3dd157SKalle Valo 21535e3dd157SKalle Valo config.num_peer_keys = __cpu_to_le32(TARGET_NUM_PEER_KEYS); 21545e3dd157SKalle Valo config.num_tids = __cpu_to_le32(TARGET_NUM_TIDS); 21555e3dd157SKalle Valo config.ast_skid_limit = __cpu_to_le32(TARGET_AST_SKID_LIMIT); 21565e3dd157SKalle Valo config.tx_chain_mask = __cpu_to_le32(TARGET_TX_CHAIN_MASK); 21575e3dd157SKalle Valo config.rx_chain_mask = __cpu_to_le32(TARGET_RX_CHAIN_MASK); 21585e3dd157SKalle Valo config.rx_timeout_pri_vo = __cpu_to_le32(TARGET_RX_TIMEOUT_LO_PRI); 21595e3dd157SKalle Valo config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_RX_TIMEOUT_LO_PRI); 21605e3dd157SKalle Valo config.rx_timeout_pri_be = __cpu_to_le32(TARGET_RX_TIMEOUT_LO_PRI); 21615e3dd157SKalle Valo config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_RX_TIMEOUT_HI_PRI); 21625e3dd157SKalle Valo config.rx_decap_mode = __cpu_to_le32(TARGET_RX_DECAP_MODE); 21635e3dd157SKalle Valo 21645e3dd157SKalle Valo config.scan_max_pending_reqs = 21655e3dd157SKalle Valo __cpu_to_le32(TARGET_SCAN_MAX_PENDING_REQS); 21665e3dd157SKalle Valo 21675e3dd157SKalle Valo config.bmiss_offload_max_vdev = 21685e3dd157SKalle Valo __cpu_to_le32(TARGET_BMISS_OFFLOAD_MAX_VDEV); 21695e3dd157SKalle Valo 21705e3dd157SKalle Valo config.roam_offload_max_vdev = 21715e3dd157SKalle Valo __cpu_to_le32(TARGET_ROAM_OFFLOAD_MAX_VDEV); 21725e3dd157SKalle Valo 21735e3dd157SKalle Valo config.roam_offload_max_ap_profiles = 21745e3dd157SKalle Valo __cpu_to_le32(TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES); 21755e3dd157SKalle Valo 21765e3dd157SKalle Valo config.num_mcast_groups = __cpu_to_le32(TARGET_NUM_MCAST_GROUPS); 21775e3dd157SKalle Valo config.num_mcast_table_elems = 21785e3dd157SKalle Valo __cpu_to_le32(TARGET_NUM_MCAST_TABLE_ELEMS); 21795e3dd157SKalle Valo 21805e3dd157SKalle Valo config.mcast2ucast_mode = __cpu_to_le32(TARGET_MCAST2UCAST_MODE); 21815e3dd157SKalle Valo config.tx_dbg_log_size = __cpu_to_le32(TARGET_TX_DBG_LOG_SIZE); 21825e3dd157SKalle Valo config.num_wds_entries = __cpu_to_le32(TARGET_NUM_WDS_ENTRIES); 21835e3dd157SKalle Valo config.dma_burst_size = __cpu_to_le32(TARGET_DMA_BURST_SIZE); 21845e3dd157SKalle Valo config.mac_aggr_delim = __cpu_to_le32(TARGET_MAC_AGGR_DELIM); 21855e3dd157SKalle Valo 21865e3dd157SKalle Valo val = TARGET_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK; 21875e3dd157SKalle Valo config.rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(val); 21885e3dd157SKalle Valo 21895e3dd157SKalle Valo config.vow_config = __cpu_to_le32(TARGET_VOW_CONFIG); 21905e3dd157SKalle Valo 21915e3dd157SKalle Valo config.gtk_offload_max_vdev = 21925e3dd157SKalle Valo __cpu_to_le32(TARGET_GTK_OFFLOAD_MAX_VDEV); 21935e3dd157SKalle Valo 21945e3dd157SKalle Valo config.num_msdu_desc = __cpu_to_le32(TARGET_NUM_MSDU_DESC); 21955e3dd157SKalle Valo config.max_frag_entries = __cpu_to_le32(TARGET_MAX_FRAG_ENTRIES); 21965e3dd157SKalle Valo 2197b3effe61SBartosz Markowski len = sizeof(*cmd) + 2198b3effe61SBartosz Markowski (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks); 2199b3effe61SBartosz Markowski 2200b3effe61SBartosz Markowski buf = ath10k_wmi_alloc_skb(len); 22015e3dd157SKalle Valo if (!buf) 22025e3dd157SKalle Valo return -ENOMEM; 22035e3dd157SKalle Valo 22045e3dd157SKalle Valo cmd = (struct wmi_init_cmd *)buf->data; 2205b3effe61SBartosz Markowski 2206b3effe61SBartosz Markowski if (ar->wmi.num_mem_chunks == 0) { 22075e3dd157SKalle Valo cmd->num_host_mem_chunks = 0; 2208b3effe61SBartosz Markowski goto out; 2209b3effe61SBartosz Markowski } 2210b3effe61SBartosz Markowski 2211b3effe61SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", 22125c54a7bfSMichal Kazior ar->wmi.num_mem_chunks); 2213b3effe61SBartosz Markowski 2214b3effe61SBartosz Markowski cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); 2215b3effe61SBartosz Markowski 2216b3effe61SBartosz Markowski for (i = 0; i < ar->wmi.num_mem_chunks; i++) { 2217b3effe61SBartosz Markowski cmd->host_mem_chunks[i].ptr = 2218b3effe61SBartosz Markowski __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); 2219b3effe61SBartosz Markowski cmd->host_mem_chunks[i].size = 2220b3effe61SBartosz Markowski __cpu_to_le32(ar->wmi.mem_chunks[i].len); 2221b3effe61SBartosz Markowski cmd->host_mem_chunks[i].req_id = 2222b3effe61SBartosz Markowski __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); 2223b3effe61SBartosz Markowski 2224b3effe61SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, 22255c54a7bfSMichal Kazior "wmi chunk %d len %d requested, addr 0x%llx\n", 2226b3effe61SBartosz Markowski i, 22275c54a7bfSMichal Kazior ar->wmi.mem_chunks[i].len, 22285c54a7bfSMichal Kazior (unsigned long long)ar->wmi.mem_chunks[i].paddr); 2229b3effe61SBartosz Markowski } 2230b3effe61SBartosz Markowski out: 22315e3dd157SKalle Valo memcpy(&cmd->resource_config, &config, sizeof(config)); 22325e3dd157SKalle Valo 22335e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi init\n"); 2234ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); 22355e3dd157SKalle Valo } 22365e3dd157SKalle Valo 223712b2b9e3SBartosz Markowski static int ath10k_wmi_10x_cmd_init(struct ath10k *ar) 223812b2b9e3SBartosz Markowski { 223912b2b9e3SBartosz Markowski struct wmi_init_cmd_10x *cmd; 224012b2b9e3SBartosz Markowski struct sk_buff *buf; 224112b2b9e3SBartosz Markowski struct wmi_resource_config_10x config = {}; 224212b2b9e3SBartosz Markowski u32 len, val; 224312b2b9e3SBartosz Markowski int i; 224412b2b9e3SBartosz Markowski 2245ec6a73f0SBartosz Markowski config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); 2246ec6a73f0SBartosz Markowski config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); 2247ec6a73f0SBartosz Markowski config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS); 2248ec6a73f0SBartosz Markowski config.num_tids = __cpu_to_le32(TARGET_10X_NUM_TIDS); 2249ec6a73f0SBartosz Markowski config.ast_skid_limit = __cpu_to_le32(TARGET_10X_AST_SKID_LIMIT); 2250ec6a73f0SBartosz Markowski config.tx_chain_mask = __cpu_to_le32(TARGET_10X_TX_CHAIN_MASK); 2251ec6a73f0SBartosz Markowski config.rx_chain_mask = __cpu_to_le32(TARGET_10X_RX_CHAIN_MASK); 2252ec6a73f0SBartosz Markowski config.rx_timeout_pri_vo = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI); 2253ec6a73f0SBartosz Markowski config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI); 2254ec6a73f0SBartosz Markowski config.rx_timeout_pri_be = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI); 2255ec6a73f0SBartosz Markowski config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_HI_PRI); 2256ec6a73f0SBartosz Markowski config.rx_decap_mode = __cpu_to_le32(TARGET_10X_RX_DECAP_MODE); 225712b2b9e3SBartosz Markowski 225812b2b9e3SBartosz Markowski config.scan_max_pending_reqs = 2259ec6a73f0SBartosz Markowski __cpu_to_le32(TARGET_10X_SCAN_MAX_PENDING_REQS); 226012b2b9e3SBartosz Markowski 226112b2b9e3SBartosz Markowski config.bmiss_offload_max_vdev = 2262ec6a73f0SBartosz Markowski __cpu_to_le32(TARGET_10X_BMISS_OFFLOAD_MAX_VDEV); 226312b2b9e3SBartosz Markowski 226412b2b9e3SBartosz Markowski config.roam_offload_max_vdev = 2265ec6a73f0SBartosz Markowski __cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_VDEV); 226612b2b9e3SBartosz Markowski 226712b2b9e3SBartosz Markowski config.roam_offload_max_ap_profiles = 2268ec6a73f0SBartosz Markowski __cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_AP_PROFILES); 226912b2b9e3SBartosz Markowski 2270ec6a73f0SBartosz Markowski config.num_mcast_groups = __cpu_to_le32(TARGET_10X_NUM_MCAST_GROUPS); 227112b2b9e3SBartosz Markowski config.num_mcast_table_elems = 2272ec6a73f0SBartosz Markowski __cpu_to_le32(TARGET_10X_NUM_MCAST_TABLE_ELEMS); 227312b2b9e3SBartosz Markowski 2274ec6a73f0SBartosz Markowski config.mcast2ucast_mode = __cpu_to_le32(TARGET_10X_MCAST2UCAST_MODE); 2275ec6a73f0SBartosz Markowski config.tx_dbg_log_size = __cpu_to_le32(TARGET_10X_TX_DBG_LOG_SIZE); 2276ec6a73f0SBartosz Markowski config.num_wds_entries = __cpu_to_le32(TARGET_10X_NUM_WDS_ENTRIES); 2277ec6a73f0SBartosz Markowski config.dma_burst_size = __cpu_to_le32(TARGET_10X_DMA_BURST_SIZE); 2278ec6a73f0SBartosz Markowski config.mac_aggr_delim = __cpu_to_le32(TARGET_10X_MAC_AGGR_DELIM); 227912b2b9e3SBartosz Markowski 2280ec6a73f0SBartosz Markowski val = TARGET_10X_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK; 228112b2b9e3SBartosz Markowski config.rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(val); 228212b2b9e3SBartosz Markowski 2283ec6a73f0SBartosz Markowski config.vow_config = __cpu_to_le32(TARGET_10X_VOW_CONFIG); 228412b2b9e3SBartosz Markowski 2285ec6a73f0SBartosz Markowski config.num_msdu_desc = __cpu_to_le32(TARGET_10X_NUM_MSDU_DESC); 2286ec6a73f0SBartosz Markowski config.max_frag_entries = __cpu_to_le32(TARGET_10X_MAX_FRAG_ENTRIES); 228712b2b9e3SBartosz Markowski 228812b2b9e3SBartosz Markowski len = sizeof(*cmd) + 228912b2b9e3SBartosz Markowski (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks); 229012b2b9e3SBartosz Markowski 229112b2b9e3SBartosz Markowski buf = ath10k_wmi_alloc_skb(len); 229212b2b9e3SBartosz Markowski if (!buf) 229312b2b9e3SBartosz Markowski return -ENOMEM; 229412b2b9e3SBartosz Markowski 229512b2b9e3SBartosz Markowski cmd = (struct wmi_init_cmd_10x *)buf->data; 229612b2b9e3SBartosz Markowski 229712b2b9e3SBartosz Markowski if (ar->wmi.num_mem_chunks == 0) { 229812b2b9e3SBartosz Markowski cmd->num_host_mem_chunks = 0; 229912b2b9e3SBartosz Markowski goto out; 230012b2b9e3SBartosz Markowski } 230112b2b9e3SBartosz Markowski 230212b2b9e3SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", 23035c54a7bfSMichal Kazior ar->wmi.num_mem_chunks); 230412b2b9e3SBartosz Markowski 230512b2b9e3SBartosz Markowski cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); 230612b2b9e3SBartosz Markowski 230712b2b9e3SBartosz Markowski for (i = 0; i < ar->wmi.num_mem_chunks; i++) { 230812b2b9e3SBartosz Markowski cmd->host_mem_chunks[i].ptr = 230912b2b9e3SBartosz Markowski __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); 231012b2b9e3SBartosz Markowski cmd->host_mem_chunks[i].size = 231112b2b9e3SBartosz Markowski __cpu_to_le32(ar->wmi.mem_chunks[i].len); 231212b2b9e3SBartosz Markowski cmd->host_mem_chunks[i].req_id = 231312b2b9e3SBartosz Markowski __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); 231412b2b9e3SBartosz Markowski 231512b2b9e3SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, 23165c54a7bfSMichal Kazior "wmi chunk %d len %d requested, addr 0x%llx\n", 231712b2b9e3SBartosz Markowski i, 23185c54a7bfSMichal Kazior ar->wmi.mem_chunks[i].len, 23195c54a7bfSMichal Kazior (unsigned long long)ar->wmi.mem_chunks[i].paddr); 232012b2b9e3SBartosz Markowski } 232112b2b9e3SBartosz Markowski out: 232212b2b9e3SBartosz Markowski memcpy(&cmd->resource_config, &config, sizeof(config)); 232312b2b9e3SBartosz Markowski 232412b2b9e3SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, "wmi init 10x\n"); 232512b2b9e3SBartosz Markowski return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); 232612b2b9e3SBartosz Markowski } 232712b2b9e3SBartosz Markowski 232812b2b9e3SBartosz Markowski int ath10k_wmi_cmd_init(struct ath10k *ar) 232912b2b9e3SBartosz Markowski { 233012b2b9e3SBartosz Markowski int ret; 233112b2b9e3SBartosz Markowski 233212b2b9e3SBartosz Markowski if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) 233312b2b9e3SBartosz Markowski ret = ath10k_wmi_10x_cmd_init(ar); 233412b2b9e3SBartosz Markowski else 233512b2b9e3SBartosz Markowski ret = ath10k_wmi_main_cmd_init(ar); 233612b2b9e3SBartosz Markowski 233712b2b9e3SBartosz Markowski return ret; 233812b2b9e3SBartosz Markowski } 233912b2b9e3SBartosz Markowski 234089b7e766SBartosz Markowski static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar, 234189b7e766SBartosz Markowski const struct wmi_start_scan_arg *arg) 23425e3dd157SKalle Valo { 23435e3dd157SKalle Valo int len; 23445e3dd157SKalle Valo 234589b7e766SBartosz Markowski if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) 234689b7e766SBartosz Markowski len = sizeof(struct wmi_start_scan_cmd_10x); 234789b7e766SBartosz Markowski else 23485e3dd157SKalle Valo len = sizeof(struct wmi_start_scan_cmd); 23495e3dd157SKalle Valo 23505e3dd157SKalle Valo if (arg->ie_len) { 23515e3dd157SKalle Valo if (!arg->ie) 23525e3dd157SKalle Valo return -EINVAL; 23535e3dd157SKalle Valo if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN) 23545e3dd157SKalle Valo return -EINVAL; 23555e3dd157SKalle Valo 23565e3dd157SKalle Valo len += sizeof(struct wmi_ie_data); 23575e3dd157SKalle Valo len += roundup(arg->ie_len, 4); 23585e3dd157SKalle Valo } 23595e3dd157SKalle Valo 23605e3dd157SKalle Valo if (arg->n_channels) { 23615e3dd157SKalle Valo if (!arg->channels) 23625e3dd157SKalle Valo return -EINVAL; 23635e3dd157SKalle Valo if (arg->n_channels > ARRAY_SIZE(arg->channels)) 23645e3dd157SKalle Valo return -EINVAL; 23655e3dd157SKalle Valo 23665e3dd157SKalle Valo len += sizeof(struct wmi_chan_list); 23675e3dd157SKalle Valo len += sizeof(__le32) * arg->n_channels; 23685e3dd157SKalle Valo } 23695e3dd157SKalle Valo 23705e3dd157SKalle Valo if (arg->n_ssids) { 23715e3dd157SKalle Valo if (!arg->ssids) 23725e3dd157SKalle Valo return -EINVAL; 23735e3dd157SKalle Valo if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID) 23745e3dd157SKalle Valo return -EINVAL; 23755e3dd157SKalle Valo 23765e3dd157SKalle Valo len += sizeof(struct wmi_ssid_list); 23775e3dd157SKalle Valo len += sizeof(struct wmi_ssid) * arg->n_ssids; 23785e3dd157SKalle Valo } 23795e3dd157SKalle Valo 23805e3dd157SKalle Valo if (arg->n_bssids) { 23815e3dd157SKalle Valo if (!arg->bssids) 23825e3dd157SKalle Valo return -EINVAL; 23835e3dd157SKalle Valo if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID) 23845e3dd157SKalle Valo return -EINVAL; 23855e3dd157SKalle Valo 23865e3dd157SKalle Valo len += sizeof(struct wmi_bssid_list); 23875e3dd157SKalle Valo len += sizeof(struct wmi_mac_addr) * arg->n_bssids; 23885e3dd157SKalle Valo } 23895e3dd157SKalle Valo 23905e3dd157SKalle Valo return len; 23915e3dd157SKalle Valo } 23925e3dd157SKalle Valo 23935e3dd157SKalle Valo int ath10k_wmi_start_scan(struct ath10k *ar, 23945e3dd157SKalle Valo const struct wmi_start_scan_arg *arg) 23955e3dd157SKalle Valo { 23965e3dd157SKalle Valo struct wmi_start_scan_cmd *cmd; 23975e3dd157SKalle Valo struct sk_buff *skb; 23985e3dd157SKalle Valo struct wmi_ie_data *ie; 23995e3dd157SKalle Valo struct wmi_chan_list *channels; 24005e3dd157SKalle Valo struct wmi_ssid_list *ssids; 24015e3dd157SKalle Valo struct wmi_bssid_list *bssids; 24025e3dd157SKalle Valo u32 scan_id; 24035e3dd157SKalle Valo u32 scan_req_id; 24045e3dd157SKalle Valo int off; 24055e3dd157SKalle Valo int len = 0; 24065e3dd157SKalle Valo int i; 24075e3dd157SKalle Valo 240889b7e766SBartosz Markowski len = ath10k_wmi_start_scan_calc_len(ar, arg); 24095e3dd157SKalle Valo if (len < 0) 24105e3dd157SKalle Valo return len; /* len contains error code here */ 24115e3dd157SKalle Valo 24125e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(len); 24135e3dd157SKalle Valo if (!skb) 24145e3dd157SKalle Valo return -ENOMEM; 24155e3dd157SKalle Valo 24165e3dd157SKalle Valo scan_id = WMI_HOST_SCAN_REQ_ID_PREFIX; 24175e3dd157SKalle Valo scan_id |= arg->scan_id; 24185e3dd157SKalle Valo 24195e3dd157SKalle Valo scan_req_id = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX; 24205e3dd157SKalle Valo scan_req_id |= arg->scan_req_id; 24215e3dd157SKalle Valo 24225e3dd157SKalle Valo cmd = (struct wmi_start_scan_cmd *)skb->data; 24235e3dd157SKalle Valo cmd->scan_id = __cpu_to_le32(scan_id); 24245e3dd157SKalle Valo cmd->scan_req_id = __cpu_to_le32(scan_req_id); 24255e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(arg->vdev_id); 24265e3dd157SKalle Valo cmd->scan_priority = __cpu_to_le32(arg->scan_priority); 24275e3dd157SKalle Valo cmd->notify_scan_events = __cpu_to_le32(arg->notify_scan_events); 24285e3dd157SKalle Valo cmd->dwell_time_active = __cpu_to_le32(arg->dwell_time_active); 24295e3dd157SKalle Valo cmd->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive); 24305e3dd157SKalle Valo cmd->min_rest_time = __cpu_to_le32(arg->min_rest_time); 24315e3dd157SKalle Valo cmd->max_rest_time = __cpu_to_le32(arg->max_rest_time); 24325e3dd157SKalle Valo cmd->repeat_probe_time = __cpu_to_le32(arg->repeat_probe_time); 24335e3dd157SKalle Valo cmd->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time); 24345e3dd157SKalle Valo cmd->idle_time = __cpu_to_le32(arg->idle_time); 24355e3dd157SKalle Valo cmd->max_scan_time = __cpu_to_le32(arg->max_scan_time); 24365e3dd157SKalle Valo cmd->probe_delay = __cpu_to_le32(arg->probe_delay); 24375e3dd157SKalle Valo cmd->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags); 24385e3dd157SKalle Valo 24395e3dd157SKalle Valo /* TLV list starts after fields included in the struct */ 244089b7e766SBartosz Markowski /* There's just one filed that differes the two start_scan 244189b7e766SBartosz Markowski * structures - burst_duration, which we are not using btw, 244289b7e766SBartosz Markowski no point to make the split here, just shift the buffer to fit with 244389b7e766SBartosz Markowski given FW */ 244489b7e766SBartosz Markowski if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) 244589b7e766SBartosz Markowski off = sizeof(struct wmi_start_scan_cmd_10x); 244689b7e766SBartosz Markowski else 244789b7e766SBartosz Markowski off = sizeof(struct wmi_start_scan_cmd); 24485e3dd157SKalle Valo 24495e3dd157SKalle Valo if (arg->n_channels) { 24505e3dd157SKalle Valo channels = (void *)skb->data + off; 24515e3dd157SKalle Valo channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG); 24525e3dd157SKalle Valo channels->num_chan = __cpu_to_le32(arg->n_channels); 24535e3dd157SKalle Valo 24545e3dd157SKalle Valo for (i = 0; i < arg->n_channels; i++) 24555e3dd157SKalle Valo channels->channel_list[i] = 24565e3dd157SKalle Valo __cpu_to_le32(arg->channels[i]); 24575e3dd157SKalle Valo 24585e3dd157SKalle Valo off += sizeof(*channels); 24595e3dd157SKalle Valo off += sizeof(__le32) * arg->n_channels; 24605e3dd157SKalle Valo } 24615e3dd157SKalle Valo 24625e3dd157SKalle Valo if (arg->n_ssids) { 24635e3dd157SKalle Valo ssids = (void *)skb->data + off; 24645e3dd157SKalle Valo ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG); 24655e3dd157SKalle Valo ssids->num_ssids = __cpu_to_le32(arg->n_ssids); 24665e3dd157SKalle Valo 24675e3dd157SKalle Valo for (i = 0; i < arg->n_ssids; i++) { 24685e3dd157SKalle Valo ssids->ssids[i].ssid_len = 24695e3dd157SKalle Valo __cpu_to_le32(arg->ssids[i].len); 24705e3dd157SKalle Valo memcpy(&ssids->ssids[i].ssid, 24715e3dd157SKalle Valo arg->ssids[i].ssid, 24725e3dd157SKalle Valo arg->ssids[i].len); 24735e3dd157SKalle Valo } 24745e3dd157SKalle Valo 24755e3dd157SKalle Valo off += sizeof(*ssids); 24765e3dd157SKalle Valo off += sizeof(struct wmi_ssid) * arg->n_ssids; 24775e3dd157SKalle Valo } 24785e3dd157SKalle Valo 24795e3dd157SKalle Valo if (arg->n_bssids) { 24805e3dd157SKalle Valo bssids = (void *)skb->data + off; 24815e3dd157SKalle Valo bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG); 24825e3dd157SKalle Valo bssids->num_bssid = __cpu_to_le32(arg->n_bssids); 24835e3dd157SKalle Valo 24845e3dd157SKalle Valo for (i = 0; i < arg->n_bssids; i++) 24855e3dd157SKalle Valo memcpy(&bssids->bssid_list[i], 24865e3dd157SKalle Valo arg->bssids[i].bssid, 24875e3dd157SKalle Valo ETH_ALEN); 24885e3dd157SKalle Valo 24895e3dd157SKalle Valo off += sizeof(*bssids); 24905e3dd157SKalle Valo off += sizeof(struct wmi_mac_addr) * arg->n_bssids; 24915e3dd157SKalle Valo } 24925e3dd157SKalle Valo 24935e3dd157SKalle Valo if (arg->ie_len) { 24945e3dd157SKalle Valo ie = (void *)skb->data + off; 24955e3dd157SKalle Valo ie->tag = __cpu_to_le32(WMI_IE_TAG); 24965e3dd157SKalle Valo ie->ie_len = __cpu_to_le32(arg->ie_len); 24975e3dd157SKalle Valo memcpy(ie->ie_data, arg->ie, arg->ie_len); 24985e3dd157SKalle Valo 24995e3dd157SKalle Valo off += sizeof(*ie); 25005e3dd157SKalle Valo off += roundup(arg->ie_len, 4); 25015e3dd157SKalle Valo } 25025e3dd157SKalle Valo 25035e3dd157SKalle Valo if (off != skb->len) { 25045e3dd157SKalle Valo dev_kfree_skb(skb); 25055e3dd157SKalle Valo return -EINVAL; 25065e3dd157SKalle Valo } 25075e3dd157SKalle Valo 25085e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi start scan\n"); 2509ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->start_scan_cmdid); 25105e3dd157SKalle Valo } 25115e3dd157SKalle Valo 25125e3dd157SKalle Valo void ath10k_wmi_start_scan_init(struct ath10k *ar, 25135e3dd157SKalle Valo struct wmi_start_scan_arg *arg) 25145e3dd157SKalle Valo { 25155e3dd157SKalle Valo /* setup commonly used values */ 25165e3dd157SKalle Valo arg->scan_req_id = 1; 25175e3dd157SKalle Valo arg->scan_priority = WMI_SCAN_PRIORITY_LOW; 25185e3dd157SKalle Valo arg->dwell_time_active = 50; 25195e3dd157SKalle Valo arg->dwell_time_passive = 150; 25205e3dd157SKalle Valo arg->min_rest_time = 50; 25215e3dd157SKalle Valo arg->max_rest_time = 500; 25225e3dd157SKalle Valo arg->repeat_probe_time = 0; 25235e3dd157SKalle Valo arg->probe_spacing_time = 0; 25245e3dd157SKalle Valo arg->idle_time = 0; 2525c322892fSBartosz Markowski arg->max_scan_time = 20000; 25265e3dd157SKalle Valo arg->probe_delay = 5; 25275e3dd157SKalle Valo arg->notify_scan_events = WMI_SCAN_EVENT_STARTED 25285e3dd157SKalle Valo | WMI_SCAN_EVENT_COMPLETED 25295e3dd157SKalle Valo | WMI_SCAN_EVENT_BSS_CHANNEL 25305e3dd157SKalle Valo | WMI_SCAN_EVENT_FOREIGN_CHANNEL 25315e3dd157SKalle Valo | WMI_SCAN_EVENT_DEQUEUED; 25325e3dd157SKalle Valo arg->scan_ctrl_flags |= WMI_SCAN_ADD_OFDM_RATES; 25335e3dd157SKalle Valo arg->scan_ctrl_flags |= WMI_SCAN_CHAN_STAT_EVENT; 25345e3dd157SKalle Valo arg->n_bssids = 1; 25355e3dd157SKalle Valo arg->bssids[0].bssid = "\xFF\xFF\xFF\xFF\xFF\xFF"; 25365e3dd157SKalle Valo } 25375e3dd157SKalle Valo 25385e3dd157SKalle Valo int ath10k_wmi_stop_scan(struct ath10k *ar, const struct wmi_stop_scan_arg *arg) 25395e3dd157SKalle Valo { 25405e3dd157SKalle Valo struct wmi_stop_scan_cmd *cmd; 25415e3dd157SKalle Valo struct sk_buff *skb; 25425e3dd157SKalle Valo u32 scan_id; 25435e3dd157SKalle Valo u32 req_id; 25445e3dd157SKalle Valo 25455e3dd157SKalle Valo if (arg->req_id > 0xFFF) 25465e3dd157SKalle Valo return -EINVAL; 25475e3dd157SKalle Valo if (arg->req_type == WMI_SCAN_STOP_ONE && arg->u.scan_id > 0xFFF) 25485e3dd157SKalle Valo return -EINVAL; 25495e3dd157SKalle Valo 25505e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 25515e3dd157SKalle Valo if (!skb) 25525e3dd157SKalle Valo return -ENOMEM; 25535e3dd157SKalle Valo 25545e3dd157SKalle Valo scan_id = arg->u.scan_id; 25555e3dd157SKalle Valo scan_id |= WMI_HOST_SCAN_REQ_ID_PREFIX; 25565e3dd157SKalle Valo 25575e3dd157SKalle Valo req_id = arg->req_id; 25585e3dd157SKalle Valo req_id |= WMI_HOST_SCAN_REQUESTOR_ID_PREFIX; 25595e3dd157SKalle Valo 25605e3dd157SKalle Valo cmd = (struct wmi_stop_scan_cmd *)skb->data; 25615e3dd157SKalle Valo cmd->req_type = __cpu_to_le32(arg->req_type); 25625e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(arg->u.vdev_id); 25635e3dd157SKalle Valo cmd->scan_id = __cpu_to_le32(scan_id); 25645e3dd157SKalle Valo cmd->scan_req_id = __cpu_to_le32(req_id); 25655e3dd157SKalle Valo 25665e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 25675e3dd157SKalle Valo "wmi stop scan reqid %d req_type %d vdev/scan_id %d\n", 25685e3dd157SKalle Valo arg->req_id, arg->req_type, arg->u.scan_id); 2569ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->stop_scan_cmdid); 25705e3dd157SKalle Valo } 25715e3dd157SKalle Valo 25725e3dd157SKalle Valo int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id, 25735e3dd157SKalle Valo enum wmi_vdev_type type, 25745e3dd157SKalle Valo enum wmi_vdev_subtype subtype, 25755e3dd157SKalle Valo const u8 macaddr[ETH_ALEN]) 25765e3dd157SKalle Valo { 25775e3dd157SKalle Valo struct wmi_vdev_create_cmd *cmd; 25785e3dd157SKalle Valo struct sk_buff *skb; 25795e3dd157SKalle Valo 25805e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 25815e3dd157SKalle Valo if (!skb) 25825e3dd157SKalle Valo return -ENOMEM; 25835e3dd157SKalle Valo 25845e3dd157SKalle Valo cmd = (struct wmi_vdev_create_cmd *)skb->data; 25855e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 25865e3dd157SKalle Valo cmd->vdev_type = __cpu_to_le32(type); 25875e3dd157SKalle Valo cmd->vdev_subtype = __cpu_to_le32(subtype); 25885e3dd157SKalle Valo memcpy(cmd->vdev_macaddr.addr, macaddr, ETH_ALEN); 25895e3dd157SKalle Valo 25905e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 25915e3dd157SKalle Valo "WMI vdev create: id %d type %d subtype %d macaddr %pM\n", 25925e3dd157SKalle Valo vdev_id, type, subtype, macaddr); 25935e3dd157SKalle Valo 2594ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_create_cmdid); 25955e3dd157SKalle Valo } 25965e3dd157SKalle Valo 25975e3dd157SKalle Valo int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id) 25985e3dd157SKalle Valo { 25995e3dd157SKalle Valo struct wmi_vdev_delete_cmd *cmd; 26005e3dd157SKalle Valo struct sk_buff *skb; 26015e3dd157SKalle Valo 26025e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 26035e3dd157SKalle Valo if (!skb) 26045e3dd157SKalle Valo return -ENOMEM; 26055e3dd157SKalle Valo 26065e3dd157SKalle Valo cmd = (struct wmi_vdev_delete_cmd *)skb->data; 26075e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 26085e3dd157SKalle Valo 26095e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 26105e3dd157SKalle Valo "WMI vdev delete id %d\n", vdev_id); 26115e3dd157SKalle Valo 2612ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_delete_cmdid); 26135e3dd157SKalle Valo } 26145e3dd157SKalle Valo 26155e3dd157SKalle Valo static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, 26165e3dd157SKalle Valo const struct wmi_vdev_start_request_arg *arg, 2617ce42870eSBartosz Markowski u32 cmd_id) 26185e3dd157SKalle Valo { 26195e3dd157SKalle Valo struct wmi_vdev_start_request_cmd *cmd; 26205e3dd157SKalle Valo struct sk_buff *skb; 26215e3dd157SKalle Valo const char *cmdname; 26225e3dd157SKalle Valo u32 flags = 0; 26235e3dd157SKalle Valo 2624ce42870eSBartosz Markowski if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid && 2625ce42870eSBartosz Markowski cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid) 26265e3dd157SKalle Valo return -EINVAL; 26275e3dd157SKalle Valo if (WARN_ON(arg->ssid && arg->ssid_len == 0)) 26285e3dd157SKalle Valo return -EINVAL; 26295e3dd157SKalle Valo if (WARN_ON(arg->hidden_ssid && !arg->ssid)) 26305e3dd157SKalle Valo return -EINVAL; 26315e3dd157SKalle Valo if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid))) 26325e3dd157SKalle Valo return -EINVAL; 26335e3dd157SKalle Valo 2634ce42870eSBartosz Markowski if (cmd_id == ar->wmi.cmd->vdev_start_request_cmdid) 26355e3dd157SKalle Valo cmdname = "start"; 2636ce42870eSBartosz Markowski else if (cmd_id == ar->wmi.cmd->vdev_restart_request_cmdid) 26375e3dd157SKalle Valo cmdname = "restart"; 26385e3dd157SKalle Valo else 26395e3dd157SKalle Valo return -EINVAL; /* should not happen, we already check cmd_id */ 26405e3dd157SKalle Valo 26415e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 26425e3dd157SKalle Valo if (!skb) 26435e3dd157SKalle Valo return -ENOMEM; 26445e3dd157SKalle Valo 26455e3dd157SKalle Valo if (arg->hidden_ssid) 26465e3dd157SKalle Valo flags |= WMI_VDEV_START_HIDDEN_SSID; 26475e3dd157SKalle Valo if (arg->pmf_enabled) 26485e3dd157SKalle Valo flags |= WMI_VDEV_START_PMF_ENABLED; 26495e3dd157SKalle Valo 26505e3dd157SKalle Valo cmd = (struct wmi_vdev_start_request_cmd *)skb->data; 26515e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(arg->vdev_id); 26525e3dd157SKalle Valo cmd->disable_hw_ack = __cpu_to_le32(arg->disable_hw_ack); 26535e3dd157SKalle Valo cmd->beacon_interval = __cpu_to_le32(arg->bcn_intval); 26545e3dd157SKalle Valo cmd->dtim_period = __cpu_to_le32(arg->dtim_period); 26555e3dd157SKalle Valo cmd->flags = __cpu_to_le32(flags); 26565e3dd157SKalle Valo cmd->bcn_tx_rate = __cpu_to_le32(arg->bcn_tx_rate); 26575e3dd157SKalle Valo cmd->bcn_tx_power = __cpu_to_le32(arg->bcn_tx_power); 26585e3dd157SKalle Valo 26595e3dd157SKalle Valo if (arg->ssid) { 26605e3dd157SKalle Valo cmd->ssid.ssid_len = __cpu_to_le32(arg->ssid_len); 26615e3dd157SKalle Valo memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len); 26625e3dd157SKalle Valo } 26635e3dd157SKalle Valo 26645e3dd157SKalle Valo cmd->chan.mhz = __cpu_to_le32(arg->channel.freq); 26655e3dd157SKalle Valo 26665e3dd157SKalle Valo cmd->chan.band_center_freq1 = 26675e3dd157SKalle Valo __cpu_to_le32(arg->channel.band_center_freq1); 26685e3dd157SKalle Valo 26695e3dd157SKalle Valo cmd->chan.mode = arg->channel.mode; 26705e3dd157SKalle Valo cmd->chan.min_power = arg->channel.min_power; 26715e3dd157SKalle Valo cmd->chan.max_power = arg->channel.max_power; 26725e3dd157SKalle Valo cmd->chan.reg_power = arg->channel.max_reg_power; 26735e3dd157SKalle Valo cmd->chan.reg_classid = arg->channel.reg_class_id; 26745e3dd157SKalle Valo cmd->chan.antenna_max = arg->channel.max_antenna_gain; 26755e3dd157SKalle Valo 26765e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 26775e3dd157SKalle Valo "wmi vdev %s id 0x%x freq %d, mode %d, ch_flags: 0x%0X," 26785e3dd157SKalle Valo "max_power: %d\n", cmdname, arg->vdev_id, arg->channel.freq, 26795e3dd157SKalle Valo arg->channel.mode, flags, arg->channel.max_power); 26805e3dd157SKalle Valo 26815e3dd157SKalle Valo return ath10k_wmi_cmd_send(ar, skb, cmd_id); 26825e3dd157SKalle Valo } 26835e3dd157SKalle Valo 26845e3dd157SKalle Valo int ath10k_wmi_vdev_start(struct ath10k *ar, 26855e3dd157SKalle Valo const struct wmi_vdev_start_request_arg *arg) 26865e3dd157SKalle Valo { 2687ce42870eSBartosz Markowski u32 cmd_id = ar->wmi.cmd->vdev_start_request_cmdid; 2688ce42870eSBartosz Markowski 2689ce42870eSBartosz Markowski return ath10k_wmi_vdev_start_restart(ar, arg, cmd_id); 26905e3dd157SKalle Valo } 26915e3dd157SKalle Valo 26925e3dd157SKalle Valo int ath10k_wmi_vdev_restart(struct ath10k *ar, 26935e3dd157SKalle Valo const struct wmi_vdev_start_request_arg *arg) 26945e3dd157SKalle Valo { 2695ce42870eSBartosz Markowski u32 cmd_id = ar->wmi.cmd->vdev_restart_request_cmdid; 2696ce42870eSBartosz Markowski 2697ce42870eSBartosz Markowski return ath10k_wmi_vdev_start_restart(ar, arg, cmd_id); 26985e3dd157SKalle Valo } 26995e3dd157SKalle Valo 27005e3dd157SKalle Valo int ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id) 27015e3dd157SKalle Valo { 27025e3dd157SKalle Valo struct wmi_vdev_stop_cmd *cmd; 27035e3dd157SKalle Valo struct sk_buff *skb; 27045e3dd157SKalle Valo 27055e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 27065e3dd157SKalle Valo if (!skb) 27075e3dd157SKalle Valo return -ENOMEM; 27085e3dd157SKalle Valo 27095e3dd157SKalle Valo cmd = (struct wmi_vdev_stop_cmd *)skb->data; 27105e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 27115e3dd157SKalle Valo 27125e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi vdev stop id 0x%x\n", vdev_id); 27135e3dd157SKalle Valo 2714ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_stop_cmdid); 27155e3dd157SKalle Valo } 27165e3dd157SKalle Valo 27175e3dd157SKalle Valo int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid) 27185e3dd157SKalle Valo { 27195e3dd157SKalle Valo struct wmi_vdev_up_cmd *cmd; 27205e3dd157SKalle Valo struct sk_buff *skb; 27215e3dd157SKalle Valo 27225e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 27235e3dd157SKalle Valo if (!skb) 27245e3dd157SKalle Valo return -ENOMEM; 27255e3dd157SKalle Valo 27265e3dd157SKalle Valo cmd = (struct wmi_vdev_up_cmd *)skb->data; 27275e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 27285e3dd157SKalle Valo cmd->vdev_assoc_id = __cpu_to_le32(aid); 27295e3dd157SKalle Valo memcpy(&cmd->vdev_bssid.addr, bssid, 6); 27305e3dd157SKalle Valo 27315e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 27325e3dd157SKalle Valo "wmi mgmt vdev up id 0x%x assoc id %d bssid %pM\n", 27335e3dd157SKalle Valo vdev_id, aid, bssid); 27345e3dd157SKalle Valo 2735ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_up_cmdid); 27365e3dd157SKalle Valo } 27375e3dd157SKalle Valo 27385e3dd157SKalle Valo int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id) 27395e3dd157SKalle Valo { 27405e3dd157SKalle Valo struct wmi_vdev_down_cmd *cmd; 27415e3dd157SKalle Valo struct sk_buff *skb; 27425e3dd157SKalle Valo 27435e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 27445e3dd157SKalle Valo if (!skb) 27455e3dd157SKalle Valo return -ENOMEM; 27465e3dd157SKalle Valo 27475e3dd157SKalle Valo cmd = (struct wmi_vdev_down_cmd *)skb->data; 27485e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 27495e3dd157SKalle Valo 27505e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 27515e3dd157SKalle Valo "wmi mgmt vdev down id 0x%x\n", vdev_id); 27525e3dd157SKalle Valo 2753ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_down_cmdid); 27545e3dd157SKalle Valo } 27555e3dd157SKalle Valo 27565e3dd157SKalle Valo int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, 27576d1506e7SBartosz Markowski u32 param_id, u32 param_value) 27585e3dd157SKalle Valo { 27595e3dd157SKalle Valo struct wmi_vdev_set_param_cmd *cmd; 27605e3dd157SKalle Valo struct sk_buff *skb; 27615e3dd157SKalle Valo 27626d1506e7SBartosz Markowski if (param_id == WMI_VDEV_PARAM_UNSUPPORTED) { 27636d1506e7SBartosz Markowski ath10k_dbg(ATH10K_DBG_WMI, 27646d1506e7SBartosz Markowski "vdev param %d not supported by firmware\n", 27656d1506e7SBartosz Markowski param_id); 2766ebc9abddSBartosz Markowski return -EOPNOTSUPP; 27676d1506e7SBartosz Markowski } 27686d1506e7SBartosz Markowski 27695e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 27705e3dd157SKalle Valo if (!skb) 27715e3dd157SKalle Valo return -ENOMEM; 27725e3dd157SKalle Valo 27735e3dd157SKalle Valo cmd = (struct wmi_vdev_set_param_cmd *)skb->data; 27745e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 27755e3dd157SKalle Valo cmd->param_id = __cpu_to_le32(param_id); 27765e3dd157SKalle Valo cmd->param_value = __cpu_to_le32(param_value); 27775e3dd157SKalle Valo 27785e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 27795e3dd157SKalle Valo "wmi vdev id 0x%x set param %d value %d\n", 27805e3dd157SKalle Valo vdev_id, param_id, param_value); 27815e3dd157SKalle Valo 2782ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_set_param_cmdid); 27835e3dd157SKalle Valo } 27845e3dd157SKalle Valo 27855e3dd157SKalle Valo int ath10k_wmi_vdev_install_key(struct ath10k *ar, 27865e3dd157SKalle Valo const struct wmi_vdev_install_key_arg *arg) 27875e3dd157SKalle Valo { 27885e3dd157SKalle Valo struct wmi_vdev_install_key_cmd *cmd; 27895e3dd157SKalle Valo struct sk_buff *skb; 27905e3dd157SKalle Valo 27915e3dd157SKalle Valo if (arg->key_cipher == WMI_CIPHER_NONE && arg->key_data != NULL) 27925e3dd157SKalle Valo return -EINVAL; 27935e3dd157SKalle Valo if (arg->key_cipher != WMI_CIPHER_NONE && arg->key_data == NULL) 27945e3dd157SKalle Valo return -EINVAL; 27955e3dd157SKalle Valo 27965e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd) + arg->key_len); 27975e3dd157SKalle Valo if (!skb) 27985e3dd157SKalle Valo return -ENOMEM; 27995e3dd157SKalle Valo 28005e3dd157SKalle Valo cmd = (struct wmi_vdev_install_key_cmd *)skb->data; 28015e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(arg->vdev_id); 28025e3dd157SKalle Valo cmd->key_idx = __cpu_to_le32(arg->key_idx); 28035e3dd157SKalle Valo cmd->key_flags = __cpu_to_le32(arg->key_flags); 28045e3dd157SKalle Valo cmd->key_cipher = __cpu_to_le32(arg->key_cipher); 28055e3dd157SKalle Valo cmd->key_len = __cpu_to_le32(arg->key_len); 28065e3dd157SKalle Valo cmd->key_txmic_len = __cpu_to_le32(arg->key_txmic_len); 28075e3dd157SKalle Valo cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len); 28085e3dd157SKalle Valo 28095e3dd157SKalle Valo if (arg->macaddr) 28105e3dd157SKalle Valo memcpy(cmd->peer_macaddr.addr, arg->macaddr, ETH_ALEN); 28115e3dd157SKalle Valo if (arg->key_data) 28125e3dd157SKalle Valo memcpy(cmd->key_data, arg->key_data, arg->key_len); 28135e3dd157SKalle Valo 2814e0c508abSMichal Kazior ath10k_dbg(ATH10K_DBG_WMI, 2815e0c508abSMichal Kazior "wmi vdev install key idx %d cipher %d len %d\n", 2816e0c508abSMichal Kazior arg->key_idx, arg->key_cipher, arg->key_len); 2817ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, 2818ce42870eSBartosz Markowski ar->wmi.cmd->vdev_install_key_cmdid); 28195e3dd157SKalle Valo } 28205e3dd157SKalle Valo 28215e3dd157SKalle Valo int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, 28225e3dd157SKalle Valo const u8 peer_addr[ETH_ALEN]) 28235e3dd157SKalle Valo { 28245e3dd157SKalle Valo struct wmi_peer_create_cmd *cmd; 28255e3dd157SKalle Valo struct sk_buff *skb; 28265e3dd157SKalle Valo 28275e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 28285e3dd157SKalle Valo if (!skb) 28295e3dd157SKalle Valo return -ENOMEM; 28305e3dd157SKalle Valo 28315e3dd157SKalle Valo cmd = (struct wmi_peer_create_cmd *)skb->data; 28325e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 28335e3dd157SKalle Valo memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); 28345e3dd157SKalle Valo 28355e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 28365e3dd157SKalle Valo "wmi peer create vdev_id %d peer_addr %pM\n", 28375e3dd157SKalle Valo vdev_id, peer_addr); 2838ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_create_cmdid); 28395e3dd157SKalle Valo } 28405e3dd157SKalle Valo 28415e3dd157SKalle Valo int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id, 28425e3dd157SKalle Valo const u8 peer_addr[ETH_ALEN]) 28435e3dd157SKalle Valo { 28445e3dd157SKalle Valo struct wmi_peer_delete_cmd *cmd; 28455e3dd157SKalle Valo struct sk_buff *skb; 28465e3dd157SKalle Valo 28475e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 28485e3dd157SKalle Valo if (!skb) 28495e3dd157SKalle Valo return -ENOMEM; 28505e3dd157SKalle Valo 28515e3dd157SKalle Valo cmd = (struct wmi_peer_delete_cmd *)skb->data; 28525e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 28535e3dd157SKalle Valo memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); 28545e3dd157SKalle Valo 28555e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 28565e3dd157SKalle Valo "wmi peer delete vdev_id %d peer_addr %pM\n", 28575e3dd157SKalle Valo vdev_id, peer_addr); 2858ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_delete_cmdid); 28595e3dd157SKalle Valo } 28605e3dd157SKalle Valo 28615e3dd157SKalle Valo int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id, 28625e3dd157SKalle Valo const u8 peer_addr[ETH_ALEN], u32 tid_bitmap) 28635e3dd157SKalle Valo { 28645e3dd157SKalle Valo struct wmi_peer_flush_tids_cmd *cmd; 28655e3dd157SKalle Valo struct sk_buff *skb; 28665e3dd157SKalle Valo 28675e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 28685e3dd157SKalle Valo if (!skb) 28695e3dd157SKalle Valo return -ENOMEM; 28705e3dd157SKalle Valo 28715e3dd157SKalle Valo cmd = (struct wmi_peer_flush_tids_cmd *)skb->data; 28725e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 28735e3dd157SKalle Valo cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap); 28745e3dd157SKalle Valo memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); 28755e3dd157SKalle Valo 28765e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 28775e3dd157SKalle Valo "wmi peer flush vdev_id %d peer_addr %pM tids %08x\n", 28785e3dd157SKalle Valo vdev_id, peer_addr, tid_bitmap); 2879ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_flush_tids_cmdid); 28805e3dd157SKalle Valo } 28815e3dd157SKalle Valo 28825e3dd157SKalle Valo int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, 28835e3dd157SKalle Valo const u8 *peer_addr, enum wmi_peer_param param_id, 28845e3dd157SKalle Valo u32 param_value) 28855e3dd157SKalle Valo { 28865e3dd157SKalle Valo struct wmi_peer_set_param_cmd *cmd; 28875e3dd157SKalle Valo struct sk_buff *skb; 28885e3dd157SKalle Valo 28895e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 28905e3dd157SKalle Valo if (!skb) 28915e3dd157SKalle Valo return -ENOMEM; 28925e3dd157SKalle Valo 28935e3dd157SKalle Valo cmd = (struct wmi_peer_set_param_cmd *)skb->data; 28945e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 28955e3dd157SKalle Valo cmd->param_id = __cpu_to_le32(param_id); 28965e3dd157SKalle Valo cmd->param_value = __cpu_to_le32(param_value); 28975e3dd157SKalle Valo memcpy(&cmd->peer_macaddr.addr, peer_addr, 6); 28985e3dd157SKalle Valo 28995e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 29005e3dd157SKalle Valo "wmi vdev %d peer 0x%pM set param %d value %d\n", 29015e3dd157SKalle Valo vdev_id, peer_addr, param_id, param_value); 29025e3dd157SKalle Valo 2903ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_set_param_cmdid); 29045e3dd157SKalle Valo } 29055e3dd157SKalle Valo 29065e3dd157SKalle Valo int ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id, 29075e3dd157SKalle Valo enum wmi_sta_ps_mode psmode) 29085e3dd157SKalle Valo { 29095e3dd157SKalle Valo struct wmi_sta_powersave_mode_cmd *cmd; 29105e3dd157SKalle Valo struct sk_buff *skb; 29115e3dd157SKalle Valo 29125e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 29135e3dd157SKalle Valo if (!skb) 29145e3dd157SKalle Valo return -ENOMEM; 29155e3dd157SKalle Valo 29165e3dd157SKalle Valo cmd = (struct wmi_sta_powersave_mode_cmd *)skb->data; 29175e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 29185e3dd157SKalle Valo cmd->sta_ps_mode = __cpu_to_le32(psmode); 29195e3dd157SKalle Valo 29205e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 29215e3dd157SKalle Valo "wmi set powersave id 0x%x mode %d\n", 29225e3dd157SKalle Valo vdev_id, psmode); 29235e3dd157SKalle Valo 2924ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, 2925ce42870eSBartosz Markowski ar->wmi.cmd->sta_powersave_mode_cmdid); 29265e3dd157SKalle Valo } 29275e3dd157SKalle Valo 29285e3dd157SKalle Valo int ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id, 29295e3dd157SKalle Valo enum wmi_sta_powersave_param param_id, 29305e3dd157SKalle Valo u32 value) 29315e3dd157SKalle Valo { 29325e3dd157SKalle Valo struct wmi_sta_powersave_param_cmd *cmd; 29335e3dd157SKalle Valo struct sk_buff *skb; 29345e3dd157SKalle Valo 29355e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 29365e3dd157SKalle Valo if (!skb) 29375e3dd157SKalle Valo return -ENOMEM; 29385e3dd157SKalle Valo 29395e3dd157SKalle Valo cmd = (struct wmi_sta_powersave_param_cmd *)skb->data; 29405e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 29415e3dd157SKalle Valo cmd->param_id = __cpu_to_le32(param_id); 29425e3dd157SKalle Valo cmd->param_value = __cpu_to_le32(value); 29435e3dd157SKalle Valo 29445e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 29455e3dd157SKalle Valo "wmi sta ps param vdev_id 0x%x param %d value %d\n", 29465e3dd157SKalle Valo vdev_id, param_id, value); 2947ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, 2948ce42870eSBartosz Markowski ar->wmi.cmd->sta_powersave_param_cmdid); 29495e3dd157SKalle Valo } 29505e3dd157SKalle Valo 29515e3dd157SKalle Valo int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac, 29525e3dd157SKalle Valo enum wmi_ap_ps_peer_param param_id, u32 value) 29535e3dd157SKalle Valo { 29545e3dd157SKalle Valo struct wmi_ap_ps_peer_cmd *cmd; 29555e3dd157SKalle Valo struct sk_buff *skb; 29565e3dd157SKalle Valo 29575e3dd157SKalle Valo if (!mac) 29585e3dd157SKalle Valo return -EINVAL; 29595e3dd157SKalle Valo 29605e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 29615e3dd157SKalle Valo if (!skb) 29625e3dd157SKalle Valo return -ENOMEM; 29635e3dd157SKalle Valo 29645e3dd157SKalle Valo cmd = (struct wmi_ap_ps_peer_cmd *)skb->data; 29655e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(vdev_id); 29665e3dd157SKalle Valo cmd->param_id = __cpu_to_le32(param_id); 29675e3dd157SKalle Valo cmd->param_value = __cpu_to_le32(value); 29685e3dd157SKalle Valo memcpy(&cmd->peer_macaddr, mac, ETH_ALEN); 29695e3dd157SKalle Valo 29705e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, 29715e3dd157SKalle Valo "wmi ap ps param vdev_id 0x%X param %d value %d mac_addr %pM\n", 29725e3dd157SKalle Valo vdev_id, param_id, value, mac); 29735e3dd157SKalle Valo 2974ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, 2975ce42870eSBartosz Markowski ar->wmi.cmd->ap_ps_peer_param_cmdid); 29765e3dd157SKalle Valo } 29775e3dd157SKalle Valo 29785e3dd157SKalle Valo int ath10k_wmi_scan_chan_list(struct ath10k *ar, 29795e3dd157SKalle Valo const struct wmi_scan_chan_list_arg *arg) 29805e3dd157SKalle Valo { 29815e3dd157SKalle Valo struct wmi_scan_chan_list_cmd *cmd; 29825e3dd157SKalle Valo struct sk_buff *skb; 29835e3dd157SKalle Valo struct wmi_channel_arg *ch; 29845e3dd157SKalle Valo struct wmi_channel *ci; 29855e3dd157SKalle Valo int len; 29865e3dd157SKalle Valo int i; 29875e3dd157SKalle Valo 29885e3dd157SKalle Valo len = sizeof(*cmd) + arg->n_channels * sizeof(struct wmi_channel); 29895e3dd157SKalle Valo 29905e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(len); 29915e3dd157SKalle Valo if (!skb) 29925e3dd157SKalle Valo return -EINVAL; 29935e3dd157SKalle Valo 29945e3dd157SKalle Valo cmd = (struct wmi_scan_chan_list_cmd *)skb->data; 29955e3dd157SKalle Valo cmd->num_scan_chans = __cpu_to_le32(arg->n_channels); 29965e3dd157SKalle Valo 29975e3dd157SKalle Valo for (i = 0; i < arg->n_channels; i++) { 29985e3dd157SKalle Valo u32 flags = 0; 29995e3dd157SKalle Valo 30005e3dd157SKalle Valo ch = &arg->channels[i]; 30015e3dd157SKalle Valo ci = &cmd->chan_info[i]; 30025e3dd157SKalle Valo 30035e3dd157SKalle Valo if (ch->passive) 30045e3dd157SKalle Valo flags |= WMI_CHAN_FLAG_PASSIVE; 30055e3dd157SKalle Valo if (ch->allow_ibss) 30065e3dd157SKalle Valo flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED; 30075e3dd157SKalle Valo if (ch->allow_ht) 30085e3dd157SKalle Valo flags |= WMI_CHAN_FLAG_ALLOW_HT; 30095e3dd157SKalle Valo if (ch->allow_vht) 30105e3dd157SKalle Valo flags |= WMI_CHAN_FLAG_ALLOW_VHT; 30115e3dd157SKalle Valo if (ch->ht40plus) 30125e3dd157SKalle Valo flags |= WMI_CHAN_FLAG_HT40_PLUS; 30135e3dd157SKalle Valo 30145e3dd157SKalle Valo ci->mhz = __cpu_to_le32(ch->freq); 30155e3dd157SKalle Valo ci->band_center_freq1 = __cpu_to_le32(ch->freq); 30165e3dd157SKalle Valo ci->band_center_freq2 = 0; 30175e3dd157SKalle Valo ci->min_power = ch->min_power; 30185e3dd157SKalle Valo ci->max_power = ch->max_power; 30195e3dd157SKalle Valo ci->reg_power = ch->max_reg_power; 30205e3dd157SKalle Valo ci->antenna_max = ch->max_antenna_gain; 30215e3dd157SKalle Valo ci->antenna_max = 0; 30225e3dd157SKalle Valo 30235e3dd157SKalle Valo /* mode & flags share storage */ 30245e3dd157SKalle Valo ci->mode = ch->mode; 30255e3dd157SKalle Valo ci->flags |= __cpu_to_le32(flags); 30265e3dd157SKalle Valo } 30275e3dd157SKalle Valo 3028ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid); 30295e3dd157SKalle Valo } 30305e3dd157SKalle Valo 30315e3dd157SKalle Valo int ath10k_wmi_peer_assoc(struct ath10k *ar, 30325e3dd157SKalle Valo const struct wmi_peer_assoc_complete_arg *arg) 30335e3dd157SKalle Valo { 30345e3dd157SKalle Valo struct wmi_peer_assoc_complete_cmd *cmd; 30355e3dd157SKalle Valo struct sk_buff *skb; 30365e3dd157SKalle Valo 30375e3dd157SKalle Valo if (arg->peer_mpdu_density > 16) 30385e3dd157SKalle Valo return -EINVAL; 30395e3dd157SKalle Valo if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES) 30405e3dd157SKalle Valo return -EINVAL; 30415e3dd157SKalle Valo if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES) 30425e3dd157SKalle Valo return -EINVAL; 30435e3dd157SKalle Valo 30445e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 30455e3dd157SKalle Valo if (!skb) 30465e3dd157SKalle Valo return -ENOMEM; 30475e3dd157SKalle Valo 30485e3dd157SKalle Valo cmd = (struct wmi_peer_assoc_complete_cmd *)skb->data; 30495e3dd157SKalle Valo cmd->vdev_id = __cpu_to_le32(arg->vdev_id); 30505e3dd157SKalle Valo cmd->peer_new_assoc = __cpu_to_le32(arg->peer_reassoc ? 0 : 1); 30515e3dd157SKalle Valo cmd->peer_associd = __cpu_to_le32(arg->peer_aid); 30525e3dd157SKalle Valo cmd->peer_flags = __cpu_to_le32(arg->peer_flags); 30535e3dd157SKalle Valo cmd->peer_caps = __cpu_to_le32(arg->peer_caps); 30545e3dd157SKalle Valo cmd->peer_listen_intval = __cpu_to_le32(arg->peer_listen_intval); 30555e3dd157SKalle Valo cmd->peer_ht_caps = __cpu_to_le32(arg->peer_ht_caps); 30565e3dd157SKalle Valo cmd->peer_max_mpdu = __cpu_to_le32(arg->peer_max_mpdu); 30575e3dd157SKalle Valo cmd->peer_mpdu_density = __cpu_to_le32(arg->peer_mpdu_density); 30585e3dd157SKalle Valo cmd->peer_rate_caps = __cpu_to_le32(arg->peer_rate_caps); 30595e3dd157SKalle Valo cmd->peer_nss = __cpu_to_le32(arg->peer_num_spatial_streams); 30605e3dd157SKalle Valo cmd->peer_vht_caps = __cpu_to_le32(arg->peer_vht_caps); 30615e3dd157SKalle Valo cmd->peer_phymode = __cpu_to_le32(arg->peer_phymode); 30625e3dd157SKalle Valo 30635e3dd157SKalle Valo memcpy(cmd->peer_macaddr.addr, arg->addr, ETH_ALEN); 30645e3dd157SKalle Valo 30655e3dd157SKalle Valo cmd->peer_legacy_rates.num_rates = 30665e3dd157SKalle Valo __cpu_to_le32(arg->peer_legacy_rates.num_rates); 30675e3dd157SKalle Valo memcpy(cmd->peer_legacy_rates.rates, arg->peer_legacy_rates.rates, 30685e3dd157SKalle Valo arg->peer_legacy_rates.num_rates); 30695e3dd157SKalle Valo 30705e3dd157SKalle Valo cmd->peer_ht_rates.num_rates = 30715e3dd157SKalle Valo __cpu_to_le32(arg->peer_ht_rates.num_rates); 30725e3dd157SKalle Valo memcpy(cmd->peer_ht_rates.rates, arg->peer_ht_rates.rates, 30735e3dd157SKalle Valo arg->peer_ht_rates.num_rates); 30745e3dd157SKalle Valo 30755e3dd157SKalle Valo cmd->peer_vht_rates.rx_max_rate = 30765e3dd157SKalle Valo __cpu_to_le32(arg->peer_vht_rates.rx_max_rate); 30775e3dd157SKalle Valo cmd->peer_vht_rates.rx_mcs_set = 30785e3dd157SKalle Valo __cpu_to_le32(arg->peer_vht_rates.rx_mcs_set); 30795e3dd157SKalle Valo cmd->peer_vht_rates.tx_max_rate = 30805e3dd157SKalle Valo __cpu_to_le32(arg->peer_vht_rates.tx_max_rate); 30815e3dd157SKalle Valo cmd->peer_vht_rates.tx_mcs_set = 30825e3dd157SKalle Valo __cpu_to_le32(arg->peer_vht_rates.tx_mcs_set); 30835e3dd157SKalle Valo 3084e0c508abSMichal Kazior ath10k_dbg(ATH10K_DBG_WMI, 3085e0c508abSMichal Kazior "wmi peer assoc vdev %d addr %pM\n", 3086e0c508abSMichal Kazior arg->vdev_id, arg->addr); 3087ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_assoc_cmdid); 30885e3dd157SKalle Valo } 30895e3dd157SKalle Valo 3090ed54388aSMichal Kazior int ath10k_wmi_beacon_send_nowait(struct ath10k *ar, 3091ed54388aSMichal Kazior const struct wmi_bcn_tx_arg *arg) 30925e3dd157SKalle Valo { 30935e3dd157SKalle Valo struct wmi_bcn_tx_cmd *cmd; 30945e3dd157SKalle Valo struct sk_buff *skb; 30955e3dd157SKalle Valo 30965e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd) + arg->bcn_len); 30975e3dd157SKalle Valo if (!skb) 30985e3dd157SKalle Valo return -ENOMEM; 30995e3dd157SKalle Valo 31005e3dd157SKalle Valo cmd = (struct wmi_bcn_tx_cmd *)skb->data; 31015e3dd157SKalle Valo cmd->hdr.vdev_id = __cpu_to_le32(arg->vdev_id); 31025e3dd157SKalle Valo cmd->hdr.tx_rate = __cpu_to_le32(arg->tx_rate); 31035e3dd157SKalle Valo cmd->hdr.tx_power = __cpu_to_le32(arg->tx_power); 31045e3dd157SKalle Valo cmd->hdr.bcn_len = __cpu_to_le32(arg->bcn_len); 31055e3dd157SKalle Valo memcpy(cmd->bcn, arg->bcn, arg->bcn_len); 31065e3dd157SKalle Valo 3107ce42870eSBartosz Markowski return ath10k_wmi_cmd_send_nowait(ar, skb, ar->wmi.cmd->bcn_tx_cmdid); 31085e3dd157SKalle Valo } 31095e3dd157SKalle Valo 31105e3dd157SKalle Valo static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params, 31115e3dd157SKalle Valo const struct wmi_wmm_params_arg *arg) 31125e3dd157SKalle Valo { 31135e3dd157SKalle Valo params->cwmin = __cpu_to_le32(arg->cwmin); 31145e3dd157SKalle Valo params->cwmax = __cpu_to_le32(arg->cwmax); 31155e3dd157SKalle Valo params->aifs = __cpu_to_le32(arg->aifs); 31165e3dd157SKalle Valo params->txop = __cpu_to_le32(arg->txop); 31175e3dd157SKalle Valo params->acm = __cpu_to_le32(arg->acm); 31185e3dd157SKalle Valo params->no_ack = __cpu_to_le32(arg->no_ack); 31195e3dd157SKalle Valo } 31205e3dd157SKalle Valo 31215e3dd157SKalle Valo int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, 31225e3dd157SKalle Valo const struct wmi_pdev_set_wmm_params_arg *arg) 31235e3dd157SKalle Valo { 31245e3dd157SKalle Valo struct wmi_pdev_set_wmm_params *cmd; 31255e3dd157SKalle Valo struct sk_buff *skb; 31265e3dd157SKalle Valo 31275e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 31285e3dd157SKalle Valo if (!skb) 31295e3dd157SKalle Valo return -ENOMEM; 31305e3dd157SKalle Valo 31315e3dd157SKalle Valo cmd = (struct wmi_pdev_set_wmm_params *)skb->data; 31325e3dd157SKalle Valo ath10k_wmi_pdev_set_wmm_param(&cmd->ac_be, &arg->ac_be); 31335e3dd157SKalle Valo ath10k_wmi_pdev_set_wmm_param(&cmd->ac_bk, &arg->ac_bk); 31345e3dd157SKalle Valo ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vi, &arg->ac_vi); 31355e3dd157SKalle Valo ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vo, &arg->ac_vo); 31365e3dd157SKalle Valo 31375e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set wmm params\n"); 3138ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, 3139ce42870eSBartosz Markowski ar->wmi.cmd->pdev_set_wmm_params_cmdid); 31405e3dd157SKalle Valo } 31415e3dd157SKalle Valo 31425e3dd157SKalle Valo int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id) 31435e3dd157SKalle Valo { 31445e3dd157SKalle Valo struct wmi_request_stats_cmd *cmd; 31455e3dd157SKalle Valo struct sk_buff *skb; 31465e3dd157SKalle Valo 31475e3dd157SKalle Valo skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 31485e3dd157SKalle Valo if (!skb) 31495e3dd157SKalle Valo return -ENOMEM; 31505e3dd157SKalle Valo 31515e3dd157SKalle Valo cmd = (struct wmi_request_stats_cmd *)skb->data; 31525e3dd157SKalle Valo cmd->stats_id = __cpu_to_le32(stats_id); 31535e3dd157SKalle Valo 31545e3dd157SKalle Valo ath10k_dbg(ATH10K_DBG_WMI, "wmi request stats %d\n", (int)stats_id); 3155ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->request_stats_cmdid); 31565e3dd157SKalle Valo } 31579cfbce75SMichal Kazior 31589cfbce75SMichal Kazior int ath10k_wmi_force_fw_hang(struct ath10k *ar, 31599cfbce75SMichal Kazior enum wmi_force_fw_hang_type type, u32 delay_ms) 31609cfbce75SMichal Kazior { 31619cfbce75SMichal Kazior struct wmi_force_fw_hang_cmd *cmd; 31629cfbce75SMichal Kazior struct sk_buff *skb; 31639cfbce75SMichal Kazior 31649cfbce75SMichal Kazior skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); 31659cfbce75SMichal Kazior if (!skb) 31669cfbce75SMichal Kazior return -ENOMEM; 31679cfbce75SMichal Kazior 31689cfbce75SMichal Kazior cmd = (struct wmi_force_fw_hang_cmd *)skb->data; 31699cfbce75SMichal Kazior cmd->type = __cpu_to_le32(type); 31709cfbce75SMichal Kazior cmd->delay_ms = __cpu_to_le32(delay_ms); 31719cfbce75SMichal Kazior 31729cfbce75SMichal Kazior ath10k_dbg(ATH10K_DBG_WMI, "wmi force fw hang %d delay %d\n", 31739cfbce75SMichal Kazior type, delay_ms); 3174ce42870eSBartosz Markowski return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid); 31759cfbce75SMichal Kazior } 3176