xref: /openbmc/linux/drivers/net/wireless/ath/ath10k/wmi.c (revision be9ce9d8)
15e3dd157SKalle Valo /*
25e3dd157SKalle Valo  * Copyright (c) 2005-2011 Atheros Communications Inc.
35e3dd157SKalle Valo  * Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
45e3dd157SKalle Valo  *
55e3dd157SKalle Valo  * Permission to use, copy, modify, and/or distribute this software for any
65e3dd157SKalle Valo  * purpose with or without fee is hereby granted, provided that the above
75e3dd157SKalle Valo  * copyright notice and this permission notice appear in all copies.
85e3dd157SKalle Valo  *
95e3dd157SKalle Valo  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
105e3dd157SKalle Valo  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
115e3dd157SKalle Valo  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
125e3dd157SKalle Valo  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
135e3dd157SKalle Valo  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
145e3dd157SKalle Valo  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
155e3dd157SKalle Valo  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
165e3dd157SKalle Valo  */
175e3dd157SKalle Valo 
185e3dd157SKalle Valo #include <linux/skbuff.h>
192fe5288cSKalle Valo #include <linux/ctype.h>
205e3dd157SKalle Valo 
215e3dd157SKalle Valo #include "core.h"
225e3dd157SKalle Valo #include "htc.h"
235e3dd157SKalle Valo #include "debug.h"
245e3dd157SKalle Valo #include "wmi.h"
25ca996ec5SMichal Kazior #include "wmi-tlv.h"
265e3dd157SKalle Valo #include "mac.h"
2743d2a30fSKalle Valo #include "testmode.h"
28d7579d12SMichal Kazior #include "wmi-ops.h"
295e3dd157SKalle Valo 
30ce42870eSBartosz Markowski /* MAIN WMI cmd track */
31ce42870eSBartosz Markowski static struct wmi_cmd_map wmi_cmd_map = {
32ce42870eSBartosz Markowski 	.init_cmdid = WMI_INIT_CMDID,
33ce42870eSBartosz Markowski 	.start_scan_cmdid = WMI_START_SCAN_CMDID,
34ce42870eSBartosz Markowski 	.stop_scan_cmdid = WMI_STOP_SCAN_CMDID,
35ce42870eSBartosz Markowski 	.scan_chan_list_cmdid = WMI_SCAN_CHAN_LIST_CMDID,
36ce42870eSBartosz Markowski 	.scan_sch_prio_tbl_cmdid = WMI_SCAN_SCH_PRIO_TBL_CMDID,
37ce42870eSBartosz Markowski 	.pdev_set_regdomain_cmdid = WMI_PDEV_SET_REGDOMAIN_CMDID,
38ce42870eSBartosz Markowski 	.pdev_set_channel_cmdid = WMI_PDEV_SET_CHANNEL_CMDID,
39ce42870eSBartosz Markowski 	.pdev_set_param_cmdid = WMI_PDEV_SET_PARAM_CMDID,
40ce42870eSBartosz Markowski 	.pdev_pktlog_enable_cmdid = WMI_PDEV_PKTLOG_ENABLE_CMDID,
41ce42870eSBartosz Markowski 	.pdev_pktlog_disable_cmdid = WMI_PDEV_PKTLOG_DISABLE_CMDID,
42ce42870eSBartosz Markowski 	.pdev_set_wmm_params_cmdid = WMI_PDEV_SET_WMM_PARAMS_CMDID,
43ce42870eSBartosz Markowski 	.pdev_set_ht_cap_ie_cmdid = WMI_PDEV_SET_HT_CAP_IE_CMDID,
44ce42870eSBartosz Markowski 	.pdev_set_vht_cap_ie_cmdid = WMI_PDEV_SET_VHT_CAP_IE_CMDID,
45ce42870eSBartosz Markowski 	.pdev_set_dscp_tid_map_cmdid = WMI_PDEV_SET_DSCP_TID_MAP_CMDID,
46ce42870eSBartosz Markowski 	.pdev_set_quiet_mode_cmdid = WMI_PDEV_SET_QUIET_MODE_CMDID,
47ce42870eSBartosz Markowski 	.pdev_green_ap_ps_enable_cmdid = WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID,
48ce42870eSBartosz Markowski 	.pdev_get_tpc_config_cmdid = WMI_PDEV_GET_TPC_CONFIG_CMDID,
49ce42870eSBartosz Markowski 	.pdev_set_base_macaddr_cmdid = WMI_PDEV_SET_BASE_MACADDR_CMDID,
50ce42870eSBartosz Markowski 	.vdev_create_cmdid = WMI_VDEV_CREATE_CMDID,
51ce42870eSBartosz Markowski 	.vdev_delete_cmdid = WMI_VDEV_DELETE_CMDID,
52ce42870eSBartosz Markowski 	.vdev_start_request_cmdid = WMI_VDEV_START_REQUEST_CMDID,
53ce42870eSBartosz Markowski 	.vdev_restart_request_cmdid = WMI_VDEV_RESTART_REQUEST_CMDID,
54ce42870eSBartosz Markowski 	.vdev_up_cmdid = WMI_VDEV_UP_CMDID,
55ce42870eSBartosz Markowski 	.vdev_stop_cmdid = WMI_VDEV_STOP_CMDID,
56ce42870eSBartosz Markowski 	.vdev_down_cmdid = WMI_VDEV_DOWN_CMDID,
57ce42870eSBartosz Markowski 	.vdev_set_param_cmdid = WMI_VDEV_SET_PARAM_CMDID,
58ce42870eSBartosz Markowski 	.vdev_install_key_cmdid = WMI_VDEV_INSTALL_KEY_CMDID,
59ce42870eSBartosz Markowski 	.peer_create_cmdid = WMI_PEER_CREATE_CMDID,
60ce42870eSBartosz Markowski 	.peer_delete_cmdid = WMI_PEER_DELETE_CMDID,
61ce42870eSBartosz Markowski 	.peer_flush_tids_cmdid = WMI_PEER_FLUSH_TIDS_CMDID,
62ce42870eSBartosz Markowski 	.peer_set_param_cmdid = WMI_PEER_SET_PARAM_CMDID,
63ce42870eSBartosz Markowski 	.peer_assoc_cmdid = WMI_PEER_ASSOC_CMDID,
64ce42870eSBartosz Markowski 	.peer_add_wds_entry_cmdid = WMI_PEER_ADD_WDS_ENTRY_CMDID,
65ce42870eSBartosz Markowski 	.peer_remove_wds_entry_cmdid = WMI_PEER_REMOVE_WDS_ENTRY_CMDID,
66ce42870eSBartosz Markowski 	.peer_mcast_group_cmdid = WMI_PEER_MCAST_GROUP_CMDID,
67ce42870eSBartosz Markowski 	.bcn_tx_cmdid = WMI_BCN_TX_CMDID,
68ce42870eSBartosz Markowski 	.pdev_send_bcn_cmdid = WMI_PDEV_SEND_BCN_CMDID,
69ce42870eSBartosz Markowski 	.bcn_tmpl_cmdid = WMI_BCN_TMPL_CMDID,
70ce42870eSBartosz Markowski 	.bcn_filter_rx_cmdid = WMI_BCN_FILTER_RX_CMDID,
71ce42870eSBartosz Markowski 	.prb_req_filter_rx_cmdid = WMI_PRB_REQ_FILTER_RX_CMDID,
72ce42870eSBartosz Markowski 	.mgmt_tx_cmdid = WMI_MGMT_TX_CMDID,
73ce42870eSBartosz Markowski 	.prb_tmpl_cmdid = WMI_PRB_TMPL_CMDID,
74ce42870eSBartosz Markowski 	.addba_clear_resp_cmdid = WMI_ADDBA_CLEAR_RESP_CMDID,
75ce42870eSBartosz Markowski 	.addba_send_cmdid = WMI_ADDBA_SEND_CMDID,
76ce42870eSBartosz Markowski 	.addba_status_cmdid = WMI_ADDBA_STATUS_CMDID,
77ce42870eSBartosz Markowski 	.delba_send_cmdid = WMI_DELBA_SEND_CMDID,
78ce42870eSBartosz Markowski 	.addba_set_resp_cmdid = WMI_ADDBA_SET_RESP_CMDID,
79ce42870eSBartosz Markowski 	.send_singleamsdu_cmdid = WMI_SEND_SINGLEAMSDU_CMDID,
80ce42870eSBartosz Markowski 	.sta_powersave_mode_cmdid = WMI_STA_POWERSAVE_MODE_CMDID,
81ce42870eSBartosz Markowski 	.sta_powersave_param_cmdid = WMI_STA_POWERSAVE_PARAM_CMDID,
82ce42870eSBartosz Markowski 	.sta_mimo_ps_mode_cmdid = WMI_STA_MIMO_PS_MODE_CMDID,
83ce42870eSBartosz Markowski 	.pdev_dfs_enable_cmdid = WMI_PDEV_DFS_ENABLE_CMDID,
84ce42870eSBartosz Markowski 	.pdev_dfs_disable_cmdid = WMI_PDEV_DFS_DISABLE_CMDID,
85ce42870eSBartosz Markowski 	.roam_scan_mode = WMI_ROAM_SCAN_MODE,
86ce42870eSBartosz Markowski 	.roam_scan_rssi_threshold = WMI_ROAM_SCAN_RSSI_THRESHOLD,
87ce42870eSBartosz Markowski 	.roam_scan_period = WMI_ROAM_SCAN_PERIOD,
88ce42870eSBartosz Markowski 	.roam_scan_rssi_change_threshold = WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
89ce42870eSBartosz Markowski 	.roam_ap_profile = WMI_ROAM_AP_PROFILE,
90ce42870eSBartosz Markowski 	.ofl_scan_add_ap_profile = WMI_ROAM_AP_PROFILE,
91ce42870eSBartosz Markowski 	.ofl_scan_remove_ap_profile = WMI_OFL_SCAN_REMOVE_AP_PROFILE,
92ce42870eSBartosz Markowski 	.ofl_scan_period = WMI_OFL_SCAN_PERIOD,
93ce42870eSBartosz Markowski 	.p2p_dev_set_device_info = WMI_P2P_DEV_SET_DEVICE_INFO,
94ce42870eSBartosz Markowski 	.p2p_dev_set_discoverability = WMI_P2P_DEV_SET_DISCOVERABILITY,
95ce42870eSBartosz Markowski 	.p2p_go_set_beacon_ie = WMI_P2P_GO_SET_BEACON_IE,
96ce42870eSBartosz Markowski 	.p2p_go_set_probe_resp_ie = WMI_P2P_GO_SET_PROBE_RESP_IE,
97ce42870eSBartosz Markowski 	.p2p_set_vendor_ie_data_cmdid = WMI_P2P_SET_VENDOR_IE_DATA_CMDID,
98ce42870eSBartosz Markowski 	.ap_ps_peer_param_cmdid = WMI_AP_PS_PEER_PARAM_CMDID,
99ce42870eSBartosz Markowski 	.ap_ps_peer_uapsd_coex_cmdid = WMI_AP_PS_PEER_UAPSD_COEX_CMDID,
100ce42870eSBartosz Markowski 	.peer_rate_retry_sched_cmdid = WMI_PEER_RATE_RETRY_SCHED_CMDID,
101ce42870eSBartosz Markowski 	.wlan_profile_trigger_cmdid = WMI_WLAN_PROFILE_TRIGGER_CMDID,
102ce42870eSBartosz Markowski 	.wlan_profile_set_hist_intvl_cmdid =
103ce42870eSBartosz Markowski 				WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
104ce42870eSBartosz Markowski 	.wlan_profile_get_profile_data_cmdid =
105ce42870eSBartosz Markowski 				WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
106ce42870eSBartosz Markowski 	.wlan_profile_enable_profile_id_cmdid =
107ce42870eSBartosz Markowski 				WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
108ce42870eSBartosz Markowski 	.wlan_profile_list_profile_id_cmdid =
109ce42870eSBartosz Markowski 				WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
110ce42870eSBartosz Markowski 	.pdev_suspend_cmdid = WMI_PDEV_SUSPEND_CMDID,
111ce42870eSBartosz Markowski 	.pdev_resume_cmdid = WMI_PDEV_RESUME_CMDID,
112ce42870eSBartosz Markowski 	.add_bcn_filter_cmdid = WMI_ADD_BCN_FILTER_CMDID,
113ce42870eSBartosz Markowski 	.rmv_bcn_filter_cmdid = WMI_RMV_BCN_FILTER_CMDID,
114ce42870eSBartosz Markowski 	.wow_add_wake_pattern_cmdid = WMI_WOW_ADD_WAKE_PATTERN_CMDID,
115ce42870eSBartosz Markowski 	.wow_del_wake_pattern_cmdid = WMI_WOW_DEL_WAKE_PATTERN_CMDID,
116ce42870eSBartosz Markowski 	.wow_enable_disable_wake_event_cmdid =
117ce42870eSBartosz Markowski 				WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
118ce42870eSBartosz Markowski 	.wow_enable_cmdid = WMI_WOW_ENABLE_CMDID,
119ce42870eSBartosz Markowski 	.wow_hostwakeup_from_sleep_cmdid = WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
120ce42870eSBartosz Markowski 	.rtt_measreq_cmdid = WMI_RTT_MEASREQ_CMDID,
121ce42870eSBartosz Markowski 	.rtt_tsf_cmdid = WMI_RTT_TSF_CMDID,
122ce42870eSBartosz Markowski 	.vdev_spectral_scan_configure_cmdid =
123ce42870eSBartosz Markowski 				WMI_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID,
124ce42870eSBartosz Markowski 	.vdev_spectral_scan_enable_cmdid = WMI_VDEV_SPECTRAL_SCAN_ENABLE_CMDID,
125ce42870eSBartosz Markowski 	.request_stats_cmdid = WMI_REQUEST_STATS_CMDID,
126ce42870eSBartosz Markowski 	.set_arp_ns_offload_cmdid = WMI_SET_ARP_NS_OFFLOAD_CMDID,
127ce42870eSBartosz Markowski 	.network_list_offload_config_cmdid =
128ce42870eSBartosz Markowski 				WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID,
129ce42870eSBartosz Markowski 	.gtk_offload_cmdid = WMI_GTK_OFFLOAD_CMDID,
130ce42870eSBartosz Markowski 	.csa_offload_enable_cmdid = WMI_CSA_OFFLOAD_ENABLE_CMDID,
131ce42870eSBartosz Markowski 	.csa_offload_chanswitch_cmdid = WMI_CSA_OFFLOAD_CHANSWITCH_CMDID,
132ce42870eSBartosz Markowski 	.chatter_set_mode_cmdid = WMI_CHATTER_SET_MODE_CMDID,
133ce42870eSBartosz Markowski 	.peer_tid_addba_cmdid = WMI_PEER_TID_ADDBA_CMDID,
134ce42870eSBartosz Markowski 	.peer_tid_delba_cmdid = WMI_PEER_TID_DELBA_CMDID,
135ce42870eSBartosz Markowski 	.sta_dtim_ps_method_cmdid = WMI_STA_DTIM_PS_METHOD_CMDID,
136ce42870eSBartosz Markowski 	.sta_uapsd_auto_trig_cmdid = WMI_STA_UAPSD_AUTO_TRIG_CMDID,
137ce42870eSBartosz Markowski 	.sta_keepalive_cmd = WMI_STA_KEEPALIVE_CMD,
138ce42870eSBartosz Markowski 	.echo_cmdid = WMI_ECHO_CMDID,
139ce42870eSBartosz Markowski 	.pdev_utf_cmdid = WMI_PDEV_UTF_CMDID,
140ce42870eSBartosz Markowski 	.dbglog_cfg_cmdid = WMI_DBGLOG_CFG_CMDID,
141ce42870eSBartosz Markowski 	.pdev_qvit_cmdid = WMI_PDEV_QVIT_CMDID,
142ce42870eSBartosz Markowski 	.pdev_ftm_intg_cmdid = WMI_PDEV_FTM_INTG_CMDID,
143ce42870eSBartosz Markowski 	.vdev_set_keepalive_cmdid = WMI_VDEV_SET_KEEPALIVE_CMDID,
144ce42870eSBartosz Markowski 	.vdev_get_keepalive_cmdid = WMI_VDEV_GET_KEEPALIVE_CMDID,
145ce42870eSBartosz Markowski 	.force_fw_hang_cmdid = WMI_FORCE_FW_HANG_CMDID,
146ce42870eSBartosz Markowski 	.gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID,
147ce42870eSBartosz Markowski 	.gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID,
148a57a6a27SRajkumar Manoharan 	.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
149ce42870eSBartosz Markowski };
150ce42870eSBartosz Markowski 
151b7e3adf9SBartosz Markowski /* 10.X WMI cmd track */
152b7e3adf9SBartosz Markowski static struct wmi_cmd_map wmi_10x_cmd_map = {
153b7e3adf9SBartosz Markowski 	.init_cmdid = WMI_10X_INIT_CMDID,
154b7e3adf9SBartosz Markowski 	.start_scan_cmdid = WMI_10X_START_SCAN_CMDID,
155b7e3adf9SBartosz Markowski 	.stop_scan_cmdid = WMI_10X_STOP_SCAN_CMDID,
156b7e3adf9SBartosz Markowski 	.scan_chan_list_cmdid = WMI_10X_SCAN_CHAN_LIST_CMDID,
15734957b25SBartosz Markowski 	.scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED,
158b7e3adf9SBartosz Markowski 	.pdev_set_regdomain_cmdid = WMI_10X_PDEV_SET_REGDOMAIN_CMDID,
159b7e3adf9SBartosz Markowski 	.pdev_set_channel_cmdid = WMI_10X_PDEV_SET_CHANNEL_CMDID,
160b7e3adf9SBartosz Markowski 	.pdev_set_param_cmdid = WMI_10X_PDEV_SET_PARAM_CMDID,
161b7e3adf9SBartosz Markowski 	.pdev_pktlog_enable_cmdid = WMI_10X_PDEV_PKTLOG_ENABLE_CMDID,
162b7e3adf9SBartosz Markowski 	.pdev_pktlog_disable_cmdid = WMI_10X_PDEV_PKTLOG_DISABLE_CMDID,
163b7e3adf9SBartosz Markowski 	.pdev_set_wmm_params_cmdid = WMI_10X_PDEV_SET_WMM_PARAMS_CMDID,
164b7e3adf9SBartosz Markowski 	.pdev_set_ht_cap_ie_cmdid = WMI_10X_PDEV_SET_HT_CAP_IE_CMDID,
165b7e3adf9SBartosz Markowski 	.pdev_set_vht_cap_ie_cmdid = WMI_10X_PDEV_SET_VHT_CAP_IE_CMDID,
166b7e3adf9SBartosz Markowski 	.pdev_set_dscp_tid_map_cmdid = WMI_10X_PDEV_SET_DSCP_TID_MAP_CMDID,
167b7e3adf9SBartosz Markowski 	.pdev_set_quiet_mode_cmdid = WMI_10X_PDEV_SET_QUIET_MODE_CMDID,
168b7e3adf9SBartosz Markowski 	.pdev_green_ap_ps_enable_cmdid = WMI_10X_PDEV_GREEN_AP_PS_ENABLE_CMDID,
169b7e3adf9SBartosz Markowski 	.pdev_get_tpc_config_cmdid = WMI_10X_PDEV_GET_TPC_CONFIG_CMDID,
170b7e3adf9SBartosz Markowski 	.pdev_set_base_macaddr_cmdid = WMI_10X_PDEV_SET_BASE_MACADDR_CMDID,
171b7e3adf9SBartosz Markowski 	.vdev_create_cmdid = WMI_10X_VDEV_CREATE_CMDID,
172b7e3adf9SBartosz Markowski 	.vdev_delete_cmdid = WMI_10X_VDEV_DELETE_CMDID,
173b7e3adf9SBartosz Markowski 	.vdev_start_request_cmdid = WMI_10X_VDEV_START_REQUEST_CMDID,
174b7e3adf9SBartosz Markowski 	.vdev_restart_request_cmdid = WMI_10X_VDEV_RESTART_REQUEST_CMDID,
175b7e3adf9SBartosz Markowski 	.vdev_up_cmdid = WMI_10X_VDEV_UP_CMDID,
176b7e3adf9SBartosz Markowski 	.vdev_stop_cmdid = WMI_10X_VDEV_STOP_CMDID,
177b7e3adf9SBartosz Markowski 	.vdev_down_cmdid = WMI_10X_VDEV_DOWN_CMDID,
178b7e3adf9SBartosz Markowski 	.vdev_set_param_cmdid = WMI_10X_VDEV_SET_PARAM_CMDID,
179b7e3adf9SBartosz Markowski 	.vdev_install_key_cmdid = WMI_10X_VDEV_INSTALL_KEY_CMDID,
180b7e3adf9SBartosz Markowski 	.peer_create_cmdid = WMI_10X_PEER_CREATE_CMDID,
181b7e3adf9SBartosz Markowski 	.peer_delete_cmdid = WMI_10X_PEER_DELETE_CMDID,
182b7e3adf9SBartosz Markowski 	.peer_flush_tids_cmdid = WMI_10X_PEER_FLUSH_TIDS_CMDID,
183b7e3adf9SBartosz Markowski 	.peer_set_param_cmdid = WMI_10X_PEER_SET_PARAM_CMDID,
184b7e3adf9SBartosz Markowski 	.peer_assoc_cmdid = WMI_10X_PEER_ASSOC_CMDID,
185b7e3adf9SBartosz Markowski 	.peer_add_wds_entry_cmdid = WMI_10X_PEER_ADD_WDS_ENTRY_CMDID,
186b7e3adf9SBartosz Markowski 	.peer_remove_wds_entry_cmdid = WMI_10X_PEER_REMOVE_WDS_ENTRY_CMDID,
187b7e3adf9SBartosz Markowski 	.peer_mcast_group_cmdid = WMI_10X_PEER_MCAST_GROUP_CMDID,
188b7e3adf9SBartosz Markowski 	.bcn_tx_cmdid = WMI_10X_BCN_TX_CMDID,
189b7e3adf9SBartosz Markowski 	.pdev_send_bcn_cmdid = WMI_10X_PDEV_SEND_BCN_CMDID,
19034957b25SBartosz Markowski 	.bcn_tmpl_cmdid = WMI_CMD_UNSUPPORTED,
191b7e3adf9SBartosz Markowski 	.bcn_filter_rx_cmdid = WMI_10X_BCN_FILTER_RX_CMDID,
192b7e3adf9SBartosz Markowski 	.prb_req_filter_rx_cmdid = WMI_10X_PRB_REQ_FILTER_RX_CMDID,
193b7e3adf9SBartosz Markowski 	.mgmt_tx_cmdid = WMI_10X_MGMT_TX_CMDID,
19434957b25SBartosz Markowski 	.prb_tmpl_cmdid = WMI_CMD_UNSUPPORTED,
195b7e3adf9SBartosz Markowski 	.addba_clear_resp_cmdid = WMI_10X_ADDBA_CLEAR_RESP_CMDID,
196b7e3adf9SBartosz Markowski 	.addba_send_cmdid = WMI_10X_ADDBA_SEND_CMDID,
197b7e3adf9SBartosz Markowski 	.addba_status_cmdid = WMI_10X_ADDBA_STATUS_CMDID,
198b7e3adf9SBartosz Markowski 	.delba_send_cmdid = WMI_10X_DELBA_SEND_CMDID,
199b7e3adf9SBartosz Markowski 	.addba_set_resp_cmdid = WMI_10X_ADDBA_SET_RESP_CMDID,
200b7e3adf9SBartosz Markowski 	.send_singleamsdu_cmdid = WMI_10X_SEND_SINGLEAMSDU_CMDID,
201b7e3adf9SBartosz Markowski 	.sta_powersave_mode_cmdid = WMI_10X_STA_POWERSAVE_MODE_CMDID,
202b7e3adf9SBartosz Markowski 	.sta_powersave_param_cmdid = WMI_10X_STA_POWERSAVE_PARAM_CMDID,
203b7e3adf9SBartosz Markowski 	.sta_mimo_ps_mode_cmdid = WMI_10X_STA_MIMO_PS_MODE_CMDID,
204b7e3adf9SBartosz Markowski 	.pdev_dfs_enable_cmdid = WMI_10X_PDEV_DFS_ENABLE_CMDID,
205b7e3adf9SBartosz Markowski 	.pdev_dfs_disable_cmdid = WMI_10X_PDEV_DFS_DISABLE_CMDID,
206b7e3adf9SBartosz Markowski 	.roam_scan_mode = WMI_10X_ROAM_SCAN_MODE,
207b7e3adf9SBartosz Markowski 	.roam_scan_rssi_threshold = WMI_10X_ROAM_SCAN_RSSI_THRESHOLD,
208b7e3adf9SBartosz Markowski 	.roam_scan_period = WMI_10X_ROAM_SCAN_PERIOD,
209b7e3adf9SBartosz Markowski 	.roam_scan_rssi_change_threshold =
210b7e3adf9SBartosz Markowski 				WMI_10X_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
211b7e3adf9SBartosz Markowski 	.roam_ap_profile = WMI_10X_ROAM_AP_PROFILE,
212b7e3adf9SBartosz Markowski 	.ofl_scan_add_ap_profile = WMI_10X_OFL_SCAN_ADD_AP_PROFILE,
213b7e3adf9SBartosz Markowski 	.ofl_scan_remove_ap_profile = WMI_10X_OFL_SCAN_REMOVE_AP_PROFILE,
214b7e3adf9SBartosz Markowski 	.ofl_scan_period = WMI_10X_OFL_SCAN_PERIOD,
215b7e3adf9SBartosz Markowski 	.p2p_dev_set_device_info = WMI_10X_P2P_DEV_SET_DEVICE_INFO,
216b7e3adf9SBartosz Markowski 	.p2p_dev_set_discoverability = WMI_10X_P2P_DEV_SET_DISCOVERABILITY,
217b7e3adf9SBartosz Markowski 	.p2p_go_set_beacon_ie = WMI_10X_P2P_GO_SET_BEACON_IE,
218b7e3adf9SBartosz Markowski 	.p2p_go_set_probe_resp_ie = WMI_10X_P2P_GO_SET_PROBE_RESP_IE,
21934957b25SBartosz Markowski 	.p2p_set_vendor_ie_data_cmdid = WMI_CMD_UNSUPPORTED,
220542fb174SJanusz Dziedzic 	.ap_ps_peer_param_cmdid = WMI_10X_AP_PS_PEER_PARAM_CMDID,
22134957b25SBartosz Markowski 	.ap_ps_peer_uapsd_coex_cmdid = WMI_CMD_UNSUPPORTED,
222b7e3adf9SBartosz Markowski 	.peer_rate_retry_sched_cmdid = WMI_10X_PEER_RATE_RETRY_SCHED_CMDID,
223b7e3adf9SBartosz Markowski 	.wlan_profile_trigger_cmdid = WMI_10X_WLAN_PROFILE_TRIGGER_CMDID,
224b7e3adf9SBartosz Markowski 	.wlan_profile_set_hist_intvl_cmdid =
225b7e3adf9SBartosz Markowski 				WMI_10X_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
226b7e3adf9SBartosz Markowski 	.wlan_profile_get_profile_data_cmdid =
227b7e3adf9SBartosz Markowski 				WMI_10X_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
228b7e3adf9SBartosz Markowski 	.wlan_profile_enable_profile_id_cmdid =
229b7e3adf9SBartosz Markowski 				WMI_10X_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
230b7e3adf9SBartosz Markowski 	.wlan_profile_list_profile_id_cmdid =
231b7e3adf9SBartosz Markowski 				WMI_10X_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
232b7e3adf9SBartosz Markowski 	.pdev_suspend_cmdid = WMI_10X_PDEV_SUSPEND_CMDID,
233b7e3adf9SBartosz Markowski 	.pdev_resume_cmdid = WMI_10X_PDEV_RESUME_CMDID,
234b7e3adf9SBartosz Markowski 	.add_bcn_filter_cmdid = WMI_10X_ADD_BCN_FILTER_CMDID,
235b7e3adf9SBartosz Markowski 	.rmv_bcn_filter_cmdid = WMI_10X_RMV_BCN_FILTER_CMDID,
236b7e3adf9SBartosz Markowski 	.wow_add_wake_pattern_cmdid = WMI_10X_WOW_ADD_WAKE_PATTERN_CMDID,
237b7e3adf9SBartosz Markowski 	.wow_del_wake_pattern_cmdid = WMI_10X_WOW_DEL_WAKE_PATTERN_CMDID,
238b7e3adf9SBartosz Markowski 	.wow_enable_disable_wake_event_cmdid =
239b7e3adf9SBartosz Markowski 				WMI_10X_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
240b7e3adf9SBartosz Markowski 	.wow_enable_cmdid = WMI_10X_WOW_ENABLE_CMDID,
241b7e3adf9SBartosz Markowski 	.wow_hostwakeup_from_sleep_cmdid =
242b7e3adf9SBartosz Markowski 				WMI_10X_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
243b7e3adf9SBartosz Markowski 	.rtt_measreq_cmdid = WMI_10X_RTT_MEASREQ_CMDID,
244b7e3adf9SBartosz Markowski 	.rtt_tsf_cmdid = WMI_10X_RTT_TSF_CMDID,
245b7e3adf9SBartosz Markowski 	.vdev_spectral_scan_configure_cmdid =
246b7e3adf9SBartosz Markowski 				WMI_10X_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID,
247b7e3adf9SBartosz Markowski 	.vdev_spectral_scan_enable_cmdid =
248b7e3adf9SBartosz Markowski 				WMI_10X_VDEV_SPECTRAL_SCAN_ENABLE_CMDID,
249b7e3adf9SBartosz Markowski 	.request_stats_cmdid = WMI_10X_REQUEST_STATS_CMDID,
25034957b25SBartosz Markowski 	.set_arp_ns_offload_cmdid = WMI_CMD_UNSUPPORTED,
25134957b25SBartosz Markowski 	.network_list_offload_config_cmdid = WMI_CMD_UNSUPPORTED,
25234957b25SBartosz Markowski 	.gtk_offload_cmdid = WMI_CMD_UNSUPPORTED,
25334957b25SBartosz Markowski 	.csa_offload_enable_cmdid = WMI_CMD_UNSUPPORTED,
25434957b25SBartosz Markowski 	.csa_offload_chanswitch_cmdid = WMI_CMD_UNSUPPORTED,
25534957b25SBartosz Markowski 	.chatter_set_mode_cmdid = WMI_CMD_UNSUPPORTED,
25634957b25SBartosz Markowski 	.peer_tid_addba_cmdid = WMI_CMD_UNSUPPORTED,
25734957b25SBartosz Markowski 	.peer_tid_delba_cmdid = WMI_CMD_UNSUPPORTED,
25834957b25SBartosz Markowski 	.sta_dtim_ps_method_cmdid = WMI_CMD_UNSUPPORTED,
25934957b25SBartosz Markowski 	.sta_uapsd_auto_trig_cmdid = WMI_CMD_UNSUPPORTED,
26034957b25SBartosz Markowski 	.sta_keepalive_cmd = WMI_CMD_UNSUPPORTED,
261b7e3adf9SBartosz Markowski 	.echo_cmdid = WMI_10X_ECHO_CMDID,
262b7e3adf9SBartosz Markowski 	.pdev_utf_cmdid = WMI_10X_PDEV_UTF_CMDID,
263b7e3adf9SBartosz Markowski 	.dbglog_cfg_cmdid = WMI_10X_DBGLOG_CFG_CMDID,
264b7e3adf9SBartosz Markowski 	.pdev_qvit_cmdid = WMI_10X_PDEV_QVIT_CMDID,
26534957b25SBartosz Markowski 	.pdev_ftm_intg_cmdid = WMI_CMD_UNSUPPORTED,
26634957b25SBartosz Markowski 	.vdev_set_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
26734957b25SBartosz Markowski 	.vdev_get_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
26834957b25SBartosz Markowski 	.force_fw_hang_cmdid = WMI_CMD_UNSUPPORTED,
269b7e3adf9SBartosz Markowski 	.gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID,
270b7e3adf9SBartosz Markowski 	.gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID,
271a57a6a27SRajkumar Manoharan 	.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
272b7e3adf9SBartosz Markowski };
273ce42870eSBartosz Markowski 
2744a16fbecSRajkumar Manoharan /* 10.2.4 WMI cmd track */
2754a16fbecSRajkumar Manoharan static struct wmi_cmd_map wmi_10_2_4_cmd_map = {
2764a16fbecSRajkumar Manoharan 	.init_cmdid = WMI_10_2_INIT_CMDID,
2774a16fbecSRajkumar Manoharan 	.start_scan_cmdid = WMI_10_2_START_SCAN_CMDID,
2784a16fbecSRajkumar Manoharan 	.stop_scan_cmdid = WMI_10_2_STOP_SCAN_CMDID,
2794a16fbecSRajkumar Manoharan 	.scan_chan_list_cmdid = WMI_10_2_SCAN_CHAN_LIST_CMDID,
2804a16fbecSRajkumar Manoharan 	.scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED,
2814a16fbecSRajkumar Manoharan 	.pdev_set_regdomain_cmdid = WMI_10_2_PDEV_SET_REGDOMAIN_CMDID,
2824a16fbecSRajkumar Manoharan 	.pdev_set_channel_cmdid = WMI_10_2_PDEV_SET_CHANNEL_CMDID,
2834a16fbecSRajkumar Manoharan 	.pdev_set_param_cmdid = WMI_10_2_PDEV_SET_PARAM_CMDID,
2844a16fbecSRajkumar Manoharan 	.pdev_pktlog_enable_cmdid = WMI_10_2_PDEV_PKTLOG_ENABLE_CMDID,
2854a16fbecSRajkumar Manoharan 	.pdev_pktlog_disable_cmdid = WMI_10_2_PDEV_PKTLOG_DISABLE_CMDID,
2864a16fbecSRajkumar Manoharan 	.pdev_set_wmm_params_cmdid = WMI_10_2_PDEV_SET_WMM_PARAMS_CMDID,
2874a16fbecSRajkumar Manoharan 	.pdev_set_ht_cap_ie_cmdid = WMI_10_2_PDEV_SET_HT_CAP_IE_CMDID,
2884a16fbecSRajkumar Manoharan 	.pdev_set_vht_cap_ie_cmdid = WMI_10_2_PDEV_SET_VHT_CAP_IE_CMDID,
2894a16fbecSRajkumar Manoharan 	.pdev_set_quiet_mode_cmdid = WMI_10_2_PDEV_SET_QUIET_MODE_CMDID,
2904a16fbecSRajkumar Manoharan 	.pdev_green_ap_ps_enable_cmdid = WMI_10_2_PDEV_GREEN_AP_PS_ENABLE_CMDID,
2914a16fbecSRajkumar Manoharan 	.pdev_get_tpc_config_cmdid = WMI_10_2_PDEV_GET_TPC_CONFIG_CMDID,
2924a16fbecSRajkumar Manoharan 	.pdev_set_base_macaddr_cmdid = WMI_10_2_PDEV_SET_BASE_MACADDR_CMDID,
2934a16fbecSRajkumar Manoharan 	.vdev_create_cmdid = WMI_10_2_VDEV_CREATE_CMDID,
2944a16fbecSRajkumar Manoharan 	.vdev_delete_cmdid = WMI_10_2_VDEV_DELETE_CMDID,
2954a16fbecSRajkumar Manoharan 	.vdev_start_request_cmdid = WMI_10_2_VDEV_START_REQUEST_CMDID,
2964a16fbecSRajkumar Manoharan 	.vdev_restart_request_cmdid = WMI_10_2_VDEV_RESTART_REQUEST_CMDID,
2974a16fbecSRajkumar Manoharan 	.vdev_up_cmdid = WMI_10_2_VDEV_UP_CMDID,
2984a16fbecSRajkumar Manoharan 	.vdev_stop_cmdid = WMI_10_2_VDEV_STOP_CMDID,
2994a16fbecSRajkumar Manoharan 	.vdev_down_cmdid = WMI_10_2_VDEV_DOWN_CMDID,
3004a16fbecSRajkumar Manoharan 	.vdev_set_param_cmdid = WMI_10_2_VDEV_SET_PARAM_CMDID,
3014a16fbecSRajkumar Manoharan 	.vdev_install_key_cmdid = WMI_10_2_VDEV_INSTALL_KEY_CMDID,
3024a16fbecSRajkumar Manoharan 	.peer_create_cmdid = WMI_10_2_PEER_CREATE_CMDID,
3034a16fbecSRajkumar Manoharan 	.peer_delete_cmdid = WMI_10_2_PEER_DELETE_CMDID,
3044a16fbecSRajkumar Manoharan 	.peer_flush_tids_cmdid = WMI_10_2_PEER_FLUSH_TIDS_CMDID,
3054a16fbecSRajkumar Manoharan 	.peer_set_param_cmdid = WMI_10_2_PEER_SET_PARAM_CMDID,
3064a16fbecSRajkumar Manoharan 	.peer_assoc_cmdid = WMI_10_2_PEER_ASSOC_CMDID,
3074a16fbecSRajkumar Manoharan 	.peer_add_wds_entry_cmdid = WMI_10_2_PEER_ADD_WDS_ENTRY_CMDID,
3084a16fbecSRajkumar Manoharan 	.peer_remove_wds_entry_cmdid = WMI_10_2_PEER_REMOVE_WDS_ENTRY_CMDID,
3094a16fbecSRajkumar Manoharan 	.peer_mcast_group_cmdid = WMI_10_2_PEER_MCAST_GROUP_CMDID,
3104a16fbecSRajkumar Manoharan 	.bcn_tx_cmdid = WMI_10_2_BCN_TX_CMDID,
3114a16fbecSRajkumar Manoharan 	.pdev_send_bcn_cmdid = WMI_10_2_PDEV_SEND_BCN_CMDID,
3124a16fbecSRajkumar Manoharan 	.bcn_tmpl_cmdid = WMI_CMD_UNSUPPORTED,
3134a16fbecSRajkumar Manoharan 	.bcn_filter_rx_cmdid = WMI_10_2_BCN_FILTER_RX_CMDID,
3144a16fbecSRajkumar Manoharan 	.prb_req_filter_rx_cmdid = WMI_10_2_PRB_REQ_FILTER_RX_CMDID,
3154a16fbecSRajkumar Manoharan 	.mgmt_tx_cmdid = WMI_10_2_MGMT_TX_CMDID,
3164a16fbecSRajkumar Manoharan 	.prb_tmpl_cmdid = WMI_CMD_UNSUPPORTED,
3174a16fbecSRajkumar Manoharan 	.addba_clear_resp_cmdid = WMI_10_2_ADDBA_CLEAR_RESP_CMDID,
3184a16fbecSRajkumar Manoharan 	.addba_send_cmdid = WMI_10_2_ADDBA_SEND_CMDID,
3194a16fbecSRajkumar Manoharan 	.addba_status_cmdid = WMI_10_2_ADDBA_STATUS_CMDID,
3204a16fbecSRajkumar Manoharan 	.delba_send_cmdid = WMI_10_2_DELBA_SEND_CMDID,
3214a16fbecSRajkumar Manoharan 	.addba_set_resp_cmdid = WMI_10_2_ADDBA_SET_RESP_CMDID,
3224a16fbecSRajkumar Manoharan 	.send_singleamsdu_cmdid = WMI_10_2_SEND_SINGLEAMSDU_CMDID,
3234a16fbecSRajkumar Manoharan 	.sta_powersave_mode_cmdid = WMI_10_2_STA_POWERSAVE_MODE_CMDID,
3244a16fbecSRajkumar Manoharan 	.sta_powersave_param_cmdid = WMI_10_2_STA_POWERSAVE_PARAM_CMDID,
3254a16fbecSRajkumar Manoharan 	.sta_mimo_ps_mode_cmdid = WMI_10_2_STA_MIMO_PS_MODE_CMDID,
3264a16fbecSRajkumar Manoharan 	.pdev_dfs_enable_cmdid = WMI_10_2_PDEV_DFS_ENABLE_CMDID,
3274a16fbecSRajkumar Manoharan 	.pdev_dfs_disable_cmdid = WMI_10_2_PDEV_DFS_DISABLE_CMDID,
3284a16fbecSRajkumar Manoharan 	.roam_scan_mode = WMI_10_2_ROAM_SCAN_MODE,
3294a16fbecSRajkumar Manoharan 	.roam_scan_rssi_threshold = WMI_10_2_ROAM_SCAN_RSSI_THRESHOLD,
3304a16fbecSRajkumar Manoharan 	.roam_scan_period = WMI_10_2_ROAM_SCAN_PERIOD,
3314a16fbecSRajkumar Manoharan 	.roam_scan_rssi_change_threshold =
3324a16fbecSRajkumar Manoharan 				WMI_10_2_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
3334a16fbecSRajkumar Manoharan 	.roam_ap_profile = WMI_10_2_ROAM_AP_PROFILE,
3344a16fbecSRajkumar Manoharan 	.ofl_scan_add_ap_profile = WMI_10_2_OFL_SCAN_ADD_AP_PROFILE,
3354a16fbecSRajkumar Manoharan 	.ofl_scan_remove_ap_profile = WMI_10_2_OFL_SCAN_REMOVE_AP_PROFILE,
3364a16fbecSRajkumar Manoharan 	.ofl_scan_period = WMI_10_2_OFL_SCAN_PERIOD,
3374a16fbecSRajkumar Manoharan 	.p2p_dev_set_device_info = WMI_10_2_P2P_DEV_SET_DEVICE_INFO,
3384a16fbecSRajkumar Manoharan 	.p2p_dev_set_discoverability = WMI_10_2_P2P_DEV_SET_DISCOVERABILITY,
3394a16fbecSRajkumar Manoharan 	.p2p_go_set_beacon_ie = WMI_10_2_P2P_GO_SET_BEACON_IE,
3404a16fbecSRajkumar Manoharan 	.p2p_go_set_probe_resp_ie = WMI_10_2_P2P_GO_SET_PROBE_RESP_IE,
3414a16fbecSRajkumar Manoharan 	.p2p_set_vendor_ie_data_cmdid = WMI_CMD_UNSUPPORTED,
3424a16fbecSRajkumar Manoharan 	.ap_ps_peer_param_cmdid = WMI_10_2_AP_PS_PEER_PARAM_CMDID,
3434a16fbecSRajkumar Manoharan 	.ap_ps_peer_uapsd_coex_cmdid = WMI_CMD_UNSUPPORTED,
3444a16fbecSRajkumar Manoharan 	.peer_rate_retry_sched_cmdid = WMI_10_2_PEER_RATE_RETRY_SCHED_CMDID,
3454a16fbecSRajkumar Manoharan 	.wlan_profile_trigger_cmdid = WMI_10_2_WLAN_PROFILE_TRIGGER_CMDID,
3464a16fbecSRajkumar Manoharan 	.wlan_profile_set_hist_intvl_cmdid =
3474a16fbecSRajkumar Manoharan 				WMI_10_2_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
3484a16fbecSRajkumar Manoharan 	.wlan_profile_get_profile_data_cmdid =
3494a16fbecSRajkumar Manoharan 				WMI_10_2_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
3504a16fbecSRajkumar Manoharan 	.wlan_profile_enable_profile_id_cmdid =
3514a16fbecSRajkumar Manoharan 				WMI_10_2_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
3524a16fbecSRajkumar Manoharan 	.wlan_profile_list_profile_id_cmdid =
3534a16fbecSRajkumar Manoharan 				WMI_10_2_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
3544a16fbecSRajkumar Manoharan 	.pdev_suspend_cmdid = WMI_10_2_PDEV_SUSPEND_CMDID,
3554a16fbecSRajkumar Manoharan 	.pdev_resume_cmdid = WMI_10_2_PDEV_RESUME_CMDID,
3564a16fbecSRajkumar Manoharan 	.add_bcn_filter_cmdid = WMI_10_2_ADD_BCN_FILTER_CMDID,
3574a16fbecSRajkumar Manoharan 	.rmv_bcn_filter_cmdid = WMI_10_2_RMV_BCN_FILTER_CMDID,
3584a16fbecSRajkumar Manoharan 	.wow_add_wake_pattern_cmdid = WMI_10_2_WOW_ADD_WAKE_PATTERN_CMDID,
3594a16fbecSRajkumar Manoharan 	.wow_del_wake_pattern_cmdid = WMI_10_2_WOW_DEL_WAKE_PATTERN_CMDID,
3604a16fbecSRajkumar Manoharan 	.wow_enable_disable_wake_event_cmdid =
3614a16fbecSRajkumar Manoharan 				WMI_10_2_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
3624a16fbecSRajkumar Manoharan 	.wow_enable_cmdid = WMI_10_2_WOW_ENABLE_CMDID,
3634a16fbecSRajkumar Manoharan 	.wow_hostwakeup_from_sleep_cmdid =
3644a16fbecSRajkumar Manoharan 				WMI_10_2_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
3654a16fbecSRajkumar Manoharan 	.rtt_measreq_cmdid = WMI_10_2_RTT_MEASREQ_CMDID,
3664a16fbecSRajkumar Manoharan 	.rtt_tsf_cmdid = WMI_10_2_RTT_TSF_CMDID,
3674a16fbecSRajkumar Manoharan 	.vdev_spectral_scan_configure_cmdid =
3684a16fbecSRajkumar Manoharan 				WMI_10_2_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID,
3694a16fbecSRajkumar Manoharan 	.vdev_spectral_scan_enable_cmdid =
3704a16fbecSRajkumar Manoharan 				WMI_10_2_VDEV_SPECTRAL_SCAN_ENABLE_CMDID,
3714a16fbecSRajkumar Manoharan 	.request_stats_cmdid = WMI_10_2_REQUEST_STATS_CMDID,
3724a16fbecSRajkumar Manoharan 	.set_arp_ns_offload_cmdid = WMI_CMD_UNSUPPORTED,
3734a16fbecSRajkumar Manoharan 	.network_list_offload_config_cmdid = WMI_CMD_UNSUPPORTED,
3744a16fbecSRajkumar Manoharan 	.gtk_offload_cmdid = WMI_CMD_UNSUPPORTED,
3754a16fbecSRajkumar Manoharan 	.csa_offload_enable_cmdid = WMI_CMD_UNSUPPORTED,
3764a16fbecSRajkumar Manoharan 	.csa_offload_chanswitch_cmdid = WMI_CMD_UNSUPPORTED,
3774a16fbecSRajkumar Manoharan 	.chatter_set_mode_cmdid = WMI_CMD_UNSUPPORTED,
3784a16fbecSRajkumar Manoharan 	.peer_tid_addba_cmdid = WMI_CMD_UNSUPPORTED,
3794a16fbecSRajkumar Manoharan 	.peer_tid_delba_cmdid = WMI_CMD_UNSUPPORTED,
3804a16fbecSRajkumar Manoharan 	.sta_dtim_ps_method_cmdid = WMI_CMD_UNSUPPORTED,
3814a16fbecSRajkumar Manoharan 	.sta_uapsd_auto_trig_cmdid = WMI_CMD_UNSUPPORTED,
3824a16fbecSRajkumar Manoharan 	.sta_keepalive_cmd = WMI_CMD_UNSUPPORTED,
3834a16fbecSRajkumar Manoharan 	.echo_cmdid = WMI_10_2_ECHO_CMDID,
3844a16fbecSRajkumar Manoharan 	.pdev_utf_cmdid = WMI_10_2_PDEV_UTF_CMDID,
3854a16fbecSRajkumar Manoharan 	.dbglog_cfg_cmdid = WMI_10_2_DBGLOG_CFG_CMDID,
3864a16fbecSRajkumar Manoharan 	.pdev_qvit_cmdid = WMI_10_2_PDEV_QVIT_CMDID,
3874a16fbecSRajkumar Manoharan 	.pdev_ftm_intg_cmdid = WMI_CMD_UNSUPPORTED,
3884a16fbecSRajkumar Manoharan 	.vdev_set_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
3894a16fbecSRajkumar Manoharan 	.vdev_get_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
3904a16fbecSRajkumar Manoharan 	.force_fw_hang_cmdid = WMI_CMD_UNSUPPORTED,
3914a16fbecSRajkumar Manoharan 	.gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID,
3924a16fbecSRajkumar Manoharan 	.gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
393a57a6a27SRajkumar Manoharan 	.pdev_get_temperature_cmdid = WMI_10_2_PDEV_GET_TEMPERATURE_CMDID,
3944a16fbecSRajkumar Manoharan };
3954a16fbecSRajkumar Manoharan 
3966d1506e7SBartosz Markowski /* MAIN WMI VDEV param map */
3976d1506e7SBartosz Markowski static struct wmi_vdev_param_map wmi_vdev_param_map = {
3986d1506e7SBartosz Markowski 	.rts_threshold = WMI_VDEV_PARAM_RTS_THRESHOLD,
3996d1506e7SBartosz Markowski 	.fragmentation_threshold = WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
4006d1506e7SBartosz Markowski 	.beacon_interval = WMI_VDEV_PARAM_BEACON_INTERVAL,
4016d1506e7SBartosz Markowski 	.listen_interval = WMI_VDEV_PARAM_LISTEN_INTERVAL,
4026d1506e7SBartosz Markowski 	.multicast_rate = WMI_VDEV_PARAM_MULTICAST_RATE,
4036d1506e7SBartosz Markowski 	.mgmt_tx_rate = WMI_VDEV_PARAM_MGMT_TX_RATE,
4046d1506e7SBartosz Markowski 	.slot_time = WMI_VDEV_PARAM_SLOT_TIME,
4056d1506e7SBartosz Markowski 	.preamble = WMI_VDEV_PARAM_PREAMBLE,
4066d1506e7SBartosz Markowski 	.swba_time = WMI_VDEV_PARAM_SWBA_TIME,
4076d1506e7SBartosz Markowski 	.wmi_vdev_stats_update_period = WMI_VDEV_STATS_UPDATE_PERIOD,
4086d1506e7SBartosz Markowski 	.wmi_vdev_pwrsave_ageout_time = WMI_VDEV_PWRSAVE_AGEOUT_TIME,
4096d1506e7SBartosz Markowski 	.wmi_vdev_host_swba_interval = WMI_VDEV_HOST_SWBA_INTERVAL,
4106d1506e7SBartosz Markowski 	.dtim_period = WMI_VDEV_PARAM_DTIM_PERIOD,
4116d1506e7SBartosz Markowski 	.wmi_vdev_oc_scheduler_air_time_limit =
4126d1506e7SBartosz Markowski 					WMI_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
4136d1506e7SBartosz Markowski 	.wds = WMI_VDEV_PARAM_WDS,
4146d1506e7SBartosz Markowski 	.atim_window = WMI_VDEV_PARAM_ATIM_WINDOW,
4156d1506e7SBartosz Markowski 	.bmiss_count_max = WMI_VDEV_PARAM_BMISS_COUNT_MAX,
4166d1506e7SBartosz Markowski 	.bmiss_first_bcnt = WMI_VDEV_PARAM_BMISS_FIRST_BCNT,
4176d1506e7SBartosz Markowski 	.bmiss_final_bcnt = WMI_VDEV_PARAM_BMISS_FINAL_BCNT,
4186d1506e7SBartosz Markowski 	.feature_wmm = WMI_VDEV_PARAM_FEATURE_WMM,
4196d1506e7SBartosz Markowski 	.chwidth = WMI_VDEV_PARAM_CHWIDTH,
4206d1506e7SBartosz Markowski 	.chextoffset = WMI_VDEV_PARAM_CHEXTOFFSET,
4216d1506e7SBartosz Markowski 	.disable_htprotection =	WMI_VDEV_PARAM_DISABLE_HTPROTECTION,
4226d1506e7SBartosz Markowski 	.sta_quickkickout = WMI_VDEV_PARAM_STA_QUICKKICKOUT,
4236d1506e7SBartosz Markowski 	.mgmt_rate = WMI_VDEV_PARAM_MGMT_RATE,
4246d1506e7SBartosz Markowski 	.protection_mode = WMI_VDEV_PARAM_PROTECTION_MODE,
4256d1506e7SBartosz Markowski 	.fixed_rate = WMI_VDEV_PARAM_FIXED_RATE,
4266d1506e7SBartosz Markowski 	.sgi = WMI_VDEV_PARAM_SGI,
4276d1506e7SBartosz Markowski 	.ldpc = WMI_VDEV_PARAM_LDPC,
4286d1506e7SBartosz Markowski 	.tx_stbc = WMI_VDEV_PARAM_TX_STBC,
4296d1506e7SBartosz Markowski 	.rx_stbc = WMI_VDEV_PARAM_RX_STBC,
4306d1506e7SBartosz Markowski 	.intra_bss_fwd = WMI_VDEV_PARAM_INTRA_BSS_FWD,
4316d1506e7SBartosz Markowski 	.def_keyid = WMI_VDEV_PARAM_DEF_KEYID,
4326d1506e7SBartosz Markowski 	.nss = WMI_VDEV_PARAM_NSS,
4336d1506e7SBartosz Markowski 	.bcast_data_rate = WMI_VDEV_PARAM_BCAST_DATA_RATE,
4346d1506e7SBartosz Markowski 	.mcast_data_rate = WMI_VDEV_PARAM_MCAST_DATA_RATE,
4356d1506e7SBartosz Markowski 	.mcast_indicate = WMI_VDEV_PARAM_MCAST_INDICATE,
4366d1506e7SBartosz Markowski 	.dhcp_indicate = WMI_VDEV_PARAM_DHCP_INDICATE,
4376d1506e7SBartosz Markowski 	.unknown_dest_indicate = WMI_VDEV_PARAM_UNKNOWN_DEST_INDICATE,
4386d1506e7SBartosz Markowski 	.ap_keepalive_min_idle_inactive_time_secs =
4396d1506e7SBartosz Markowski 			WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
4406d1506e7SBartosz Markowski 	.ap_keepalive_max_idle_inactive_time_secs =
4416d1506e7SBartosz Markowski 			WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
4426d1506e7SBartosz Markowski 	.ap_keepalive_max_unresponsive_time_secs =
4436d1506e7SBartosz Markowski 			WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
4446d1506e7SBartosz Markowski 	.ap_enable_nawds = WMI_VDEV_PARAM_AP_ENABLE_NAWDS,
4456d1506e7SBartosz Markowski 	.mcast2ucast_set = WMI_VDEV_PARAM_UNSUPPORTED,
4466d1506e7SBartosz Markowski 	.enable_rtscts = WMI_VDEV_PARAM_ENABLE_RTSCTS,
4476d1506e7SBartosz Markowski 	.txbf = WMI_VDEV_PARAM_TXBF,
4486d1506e7SBartosz Markowski 	.packet_powersave = WMI_VDEV_PARAM_PACKET_POWERSAVE,
4496d1506e7SBartosz Markowski 	.drop_unencry = WMI_VDEV_PARAM_DROP_UNENCRY,
4506d1506e7SBartosz Markowski 	.tx_encap_type = WMI_VDEV_PARAM_TX_ENCAP_TYPE,
4516d1506e7SBartosz Markowski 	.ap_detect_out_of_sync_sleeping_sta_time_secs =
4526d1506e7SBartosz Markowski 					WMI_VDEV_PARAM_UNSUPPORTED,
4536d1506e7SBartosz Markowski };
4546d1506e7SBartosz Markowski 
4556d1506e7SBartosz Markowski /* 10.X WMI VDEV param map */
4566d1506e7SBartosz Markowski static struct wmi_vdev_param_map wmi_10x_vdev_param_map = {
4576d1506e7SBartosz Markowski 	.rts_threshold = WMI_10X_VDEV_PARAM_RTS_THRESHOLD,
4586d1506e7SBartosz Markowski 	.fragmentation_threshold = WMI_10X_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
4596d1506e7SBartosz Markowski 	.beacon_interval = WMI_10X_VDEV_PARAM_BEACON_INTERVAL,
4606d1506e7SBartosz Markowski 	.listen_interval = WMI_10X_VDEV_PARAM_LISTEN_INTERVAL,
4616d1506e7SBartosz Markowski 	.multicast_rate = WMI_10X_VDEV_PARAM_MULTICAST_RATE,
4626d1506e7SBartosz Markowski 	.mgmt_tx_rate = WMI_10X_VDEV_PARAM_MGMT_TX_RATE,
4636d1506e7SBartosz Markowski 	.slot_time = WMI_10X_VDEV_PARAM_SLOT_TIME,
4646d1506e7SBartosz Markowski 	.preamble = WMI_10X_VDEV_PARAM_PREAMBLE,
4656d1506e7SBartosz Markowski 	.swba_time = WMI_10X_VDEV_PARAM_SWBA_TIME,
4666d1506e7SBartosz Markowski 	.wmi_vdev_stats_update_period = WMI_10X_VDEV_STATS_UPDATE_PERIOD,
4676d1506e7SBartosz Markowski 	.wmi_vdev_pwrsave_ageout_time = WMI_10X_VDEV_PWRSAVE_AGEOUT_TIME,
4686d1506e7SBartosz Markowski 	.wmi_vdev_host_swba_interval = WMI_10X_VDEV_HOST_SWBA_INTERVAL,
4696d1506e7SBartosz Markowski 	.dtim_period = WMI_10X_VDEV_PARAM_DTIM_PERIOD,
4706d1506e7SBartosz Markowski 	.wmi_vdev_oc_scheduler_air_time_limit =
4716d1506e7SBartosz Markowski 				WMI_10X_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
4726d1506e7SBartosz Markowski 	.wds = WMI_10X_VDEV_PARAM_WDS,
4736d1506e7SBartosz Markowski 	.atim_window = WMI_10X_VDEV_PARAM_ATIM_WINDOW,
4746d1506e7SBartosz Markowski 	.bmiss_count_max = WMI_10X_VDEV_PARAM_BMISS_COUNT_MAX,
4756d1506e7SBartosz Markowski 	.bmiss_first_bcnt = WMI_VDEV_PARAM_UNSUPPORTED,
4766d1506e7SBartosz Markowski 	.bmiss_final_bcnt = WMI_VDEV_PARAM_UNSUPPORTED,
4776d1506e7SBartosz Markowski 	.feature_wmm = WMI_10X_VDEV_PARAM_FEATURE_WMM,
4786d1506e7SBartosz Markowski 	.chwidth = WMI_10X_VDEV_PARAM_CHWIDTH,
4796d1506e7SBartosz Markowski 	.chextoffset = WMI_10X_VDEV_PARAM_CHEXTOFFSET,
4806d1506e7SBartosz Markowski 	.disable_htprotection = WMI_10X_VDEV_PARAM_DISABLE_HTPROTECTION,
4816d1506e7SBartosz Markowski 	.sta_quickkickout = WMI_10X_VDEV_PARAM_STA_QUICKKICKOUT,
4826d1506e7SBartosz Markowski 	.mgmt_rate = WMI_10X_VDEV_PARAM_MGMT_RATE,
4836d1506e7SBartosz Markowski 	.protection_mode = WMI_10X_VDEV_PARAM_PROTECTION_MODE,
4846d1506e7SBartosz Markowski 	.fixed_rate = WMI_10X_VDEV_PARAM_FIXED_RATE,
4856d1506e7SBartosz Markowski 	.sgi = WMI_10X_VDEV_PARAM_SGI,
4866d1506e7SBartosz Markowski 	.ldpc = WMI_10X_VDEV_PARAM_LDPC,
4876d1506e7SBartosz Markowski 	.tx_stbc = WMI_10X_VDEV_PARAM_TX_STBC,
4886d1506e7SBartosz Markowski 	.rx_stbc = WMI_10X_VDEV_PARAM_RX_STBC,
4896d1506e7SBartosz Markowski 	.intra_bss_fwd = WMI_10X_VDEV_PARAM_INTRA_BSS_FWD,
4906d1506e7SBartosz Markowski 	.def_keyid = WMI_10X_VDEV_PARAM_DEF_KEYID,
4916d1506e7SBartosz Markowski 	.nss = WMI_10X_VDEV_PARAM_NSS,
4926d1506e7SBartosz Markowski 	.bcast_data_rate = WMI_10X_VDEV_PARAM_BCAST_DATA_RATE,
4936d1506e7SBartosz Markowski 	.mcast_data_rate = WMI_10X_VDEV_PARAM_MCAST_DATA_RATE,
4946d1506e7SBartosz Markowski 	.mcast_indicate = WMI_10X_VDEV_PARAM_MCAST_INDICATE,
4956d1506e7SBartosz Markowski 	.dhcp_indicate = WMI_10X_VDEV_PARAM_DHCP_INDICATE,
4966d1506e7SBartosz Markowski 	.unknown_dest_indicate = WMI_10X_VDEV_PARAM_UNKNOWN_DEST_INDICATE,
4976d1506e7SBartosz Markowski 	.ap_keepalive_min_idle_inactive_time_secs =
4986d1506e7SBartosz Markowski 		WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
4996d1506e7SBartosz Markowski 	.ap_keepalive_max_idle_inactive_time_secs =
5006d1506e7SBartosz Markowski 		WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
5016d1506e7SBartosz Markowski 	.ap_keepalive_max_unresponsive_time_secs =
5026d1506e7SBartosz Markowski 		WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
5036d1506e7SBartosz Markowski 	.ap_enable_nawds = WMI_10X_VDEV_PARAM_AP_ENABLE_NAWDS,
5046d1506e7SBartosz Markowski 	.mcast2ucast_set = WMI_10X_VDEV_PARAM_MCAST2UCAST_SET,
5056d1506e7SBartosz Markowski 	.enable_rtscts = WMI_10X_VDEV_PARAM_ENABLE_RTSCTS,
5066d1506e7SBartosz Markowski 	.txbf = WMI_VDEV_PARAM_UNSUPPORTED,
5076d1506e7SBartosz Markowski 	.packet_powersave = WMI_VDEV_PARAM_UNSUPPORTED,
5086d1506e7SBartosz Markowski 	.drop_unencry = WMI_VDEV_PARAM_UNSUPPORTED,
5096d1506e7SBartosz Markowski 	.tx_encap_type = WMI_VDEV_PARAM_UNSUPPORTED,
5106d1506e7SBartosz Markowski 	.ap_detect_out_of_sync_sleeping_sta_time_secs =
5116d1506e7SBartosz Markowski 		WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS,
5126d1506e7SBartosz Markowski };
5136d1506e7SBartosz Markowski 
5144a16fbecSRajkumar Manoharan static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = {
5154a16fbecSRajkumar Manoharan 	.rts_threshold = WMI_10X_VDEV_PARAM_RTS_THRESHOLD,
5164a16fbecSRajkumar Manoharan 	.fragmentation_threshold = WMI_10X_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
5174a16fbecSRajkumar Manoharan 	.beacon_interval = WMI_10X_VDEV_PARAM_BEACON_INTERVAL,
5184a16fbecSRajkumar Manoharan 	.listen_interval = WMI_10X_VDEV_PARAM_LISTEN_INTERVAL,
5194a16fbecSRajkumar Manoharan 	.multicast_rate = WMI_10X_VDEV_PARAM_MULTICAST_RATE,
5204a16fbecSRajkumar Manoharan 	.mgmt_tx_rate = WMI_10X_VDEV_PARAM_MGMT_TX_RATE,
5214a16fbecSRajkumar Manoharan 	.slot_time = WMI_10X_VDEV_PARAM_SLOT_TIME,
5224a16fbecSRajkumar Manoharan 	.preamble = WMI_10X_VDEV_PARAM_PREAMBLE,
5234a16fbecSRajkumar Manoharan 	.swba_time = WMI_10X_VDEV_PARAM_SWBA_TIME,
5244a16fbecSRajkumar Manoharan 	.wmi_vdev_stats_update_period = WMI_10X_VDEV_STATS_UPDATE_PERIOD,
5254a16fbecSRajkumar Manoharan 	.wmi_vdev_pwrsave_ageout_time = WMI_10X_VDEV_PWRSAVE_AGEOUT_TIME,
5264a16fbecSRajkumar Manoharan 	.wmi_vdev_host_swba_interval = WMI_10X_VDEV_HOST_SWBA_INTERVAL,
5274a16fbecSRajkumar Manoharan 	.dtim_period = WMI_10X_VDEV_PARAM_DTIM_PERIOD,
5284a16fbecSRajkumar Manoharan 	.wmi_vdev_oc_scheduler_air_time_limit =
5294a16fbecSRajkumar Manoharan 				WMI_10X_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
5304a16fbecSRajkumar Manoharan 	.wds = WMI_10X_VDEV_PARAM_WDS,
5314a16fbecSRajkumar Manoharan 	.atim_window = WMI_10X_VDEV_PARAM_ATIM_WINDOW,
5324a16fbecSRajkumar Manoharan 	.bmiss_count_max = WMI_10X_VDEV_PARAM_BMISS_COUNT_MAX,
5334a16fbecSRajkumar Manoharan 	.bmiss_first_bcnt = WMI_VDEV_PARAM_UNSUPPORTED,
5344a16fbecSRajkumar Manoharan 	.bmiss_final_bcnt = WMI_VDEV_PARAM_UNSUPPORTED,
5354a16fbecSRajkumar Manoharan 	.feature_wmm = WMI_10X_VDEV_PARAM_FEATURE_WMM,
5364a16fbecSRajkumar Manoharan 	.chwidth = WMI_10X_VDEV_PARAM_CHWIDTH,
5374a16fbecSRajkumar Manoharan 	.chextoffset = WMI_10X_VDEV_PARAM_CHEXTOFFSET,
5384a16fbecSRajkumar Manoharan 	.disable_htprotection = WMI_10X_VDEV_PARAM_DISABLE_HTPROTECTION,
5394a16fbecSRajkumar Manoharan 	.sta_quickkickout = WMI_10X_VDEV_PARAM_STA_QUICKKICKOUT,
5404a16fbecSRajkumar Manoharan 	.mgmt_rate = WMI_10X_VDEV_PARAM_MGMT_RATE,
5414a16fbecSRajkumar Manoharan 	.protection_mode = WMI_10X_VDEV_PARAM_PROTECTION_MODE,
5424a16fbecSRajkumar Manoharan 	.fixed_rate = WMI_10X_VDEV_PARAM_FIXED_RATE,
5434a16fbecSRajkumar Manoharan 	.sgi = WMI_10X_VDEV_PARAM_SGI,
5444a16fbecSRajkumar Manoharan 	.ldpc = WMI_10X_VDEV_PARAM_LDPC,
5454a16fbecSRajkumar Manoharan 	.tx_stbc = WMI_10X_VDEV_PARAM_TX_STBC,
5464a16fbecSRajkumar Manoharan 	.rx_stbc = WMI_10X_VDEV_PARAM_RX_STBC,
5474a16fbecSRajkumar Manoharan 	.intra_bss_fwd = WMI_10X_VDEV_PARAM_INTRA_BSS_FWD,
5484a16fbecSRajkumar Manoharan 	.def_keyid = WMI_10X_VDEV_PARAM_DEF_KEYID,
5494a16fbecSRajkumar Manoharan 	.nss = WMI_10X_VDEV_PARAM_NSS,
5504a16fbecSRajkumar Manoharan 	.bcast_data_rate = WMI_10X_VDEV_PARAM_BCAST_DATA_RATE,
5514a16fbecSRajkumar Manoharan 	.mcast_data_rate = WMI_10X_VDEV_PARAM_MCAST_DATA_RATE,
5524a16fbecSRajkumar Manoharan 	.mcast_indicate = WMI_10X_VDEV_PARAM_MCAST_INDICATE,
5534a16fbecSRajkumar Manoharan 	.dhcp_indicate = WMI_10X_VDEV_PARAM_DHCP_INDICATE,
5544a16fbecSRajkumar Manoharan 	.unknown_dest_indicate = WMI_10X_VDEV_PARAM_UNKNOWN_DEST_INDICATE,
5554a16fbecSRajkumar Manoharan 	.ap_keepalive_min_idle_inactive_time_secs =
5564a16fbecSRajkumar Manoharan 		WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
5574a16fbecSRajkumar Manoharan 	.ap_keepalive_max_idle_inactive_time_secs =
5584a16fbecSRajkumar Manoharan 		WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
5594a16fbecSRajkumar Manoharan 	.ap_keepalive_max_unresponsive_time_secs =
5604a16fbecSRajkumar Manoharan 		WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
5614a16fbecSRajkumar Manoharan 	.ap_enable_nawds = WMI_10X_VDEV_PARAM_AP_ENABLE_NAWDS,
5624a16fbecSRajkumar Manoharan 	.mcast2ucast_set = WMI_10X_VDEV_PARAM_MCAST2UCAST_SET,
5634a16fbecSRajkumar Manoharan 	.enable_rtscts = WMI_10X_VDEV_PARAM_ENABLE_RTSCTS,
5644a16fbecSRajkumar Manoharan 	.txbf = WMI_VDEV_PARAM_UNSUPPORTED,
5654a16fbecSRajkumar Manoharan 	.packet_powersave = WMI_VDEV_PARAM_UNSUPPORTED,
5664a16fbecSRajkumar Manoharan 	.drop_unencry = WMI_VDEV_PARAM_UNSUPPORTED,
5674a16fbecSRajkumar Manoharan 	.tx_encap_type = WMI_VDEV_PARAM_UNSUPPORTED,
5684a16fbecSRajkumar Manoharan 	.ap_detect_out_of_sync_sleeping_sta_time_secs =
5694a16fbecSRajkumar Manoharan 		WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS,
5704a16fbecSRajkumar Manoharan };
5714a16fbecSRajkumar Manoharan 
572226a339bSBartosz Markowski static struct wmi_pdev_param_map wmi_pdev_param_map = {
573226a339bSBartosz Markowski 	.tx_chain_mask = WMI_PDEV_PARAM_TX_CHAIN_MASK,
574226a339bSBartosz Markowski 	.rx_chain_mask = WMI_PDEV_PARAM_RX_CHAIN_MASK,
575226a339bSBartosz Markowski 	.txpower_limit2g = WMI_PDEV_PARAM_TXPOWER_LIMIT2G,
576226a339bSBartosz Markowski 	.txpower_limit5g = WMI_PDEV_PARAM_TXPOWER_LIMIT5G,
577226a339bSBartosz Markowski 	.txpower_scale = WMI_PDEV_PARAM_TXPOWER_SCALE,
578226a339bSBartosz Markowski 	.beacon_gen_mode = WMI_PDEV_PARAM_BEACON_GEN_MODE,
579226a339bSBartosz Markowski 	.beacon_tx_mode = WMI_PDEV_PARAM_BEACON_TX_MODE,
580226a339bSBartosz Markowski 	.resmgr_offchan_mode = WMI_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
581226a339bSBartosz Markowski 	.protection_mode = WMI_PDEV_PARAM_PROTECTION_MODE,
582226a339bSBartosz Markowski 	.dynamic_bw = WMI_PDEV_PARAM_DYNAMIC_BW,
583226a339bSBartosz Markowski 	.non_agg_sw_retry_th = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
584226a339bSBartosz Markowski 	.agg_sw_retry_th = WMI_PDEV_PARAM_AGG_SW_RETRY_TH,
585226a339bSBartosz Markowski 	.sta_kickout_th = WMI_PDEV_PARAM_STA_KICKOUT_TH,
586226a339bSBartosz Markowski 	.ac_aggrsize_scaling = WMI_PDEV_PARAM_AC_AGGRSIZE_SCALING,
587226a339bSBartosz Markowski 	.ltr_enable = WMI_PDEV_PARAM_LTR_ENABLE,
588226a339bSBartosz Markowski 	.ltr_ac_latency_be = WMI_PDEV_PARAM_LTR_AC_LATENCY_BE,
589226a339bSBartosz Markowski 	.ltr_ac_latency_bk = WMI_PDEV_PARAM_LTR_AC_LATENCY_BK,
590226a339bSBartosz Markowski 	.ltr_ac_latency_vi = WMI_PDEV_PARAM_LTR_AC_LATENCY_VI,
591226a339bSBartosz Markowski 	.ltr_ac_latency_vo = WMI_PDEV_PARAM_LTR_AC_LATENCY_VO,
592226a339bSBartosz Markowski 	.ltr_ac_latency_timeout = WMI_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT,
593226a339bSBartosz Markowski 	.ltr_sleep_override = WMI_PDEV_PARAM_LTR_SLEEP_OVERRIDE,
594226a339bSBartosz Markowski 	.ltr_rx_override = WMI_PDEV_PARAM_LTR_RX_OVERRIDE,
595226a339bSBartosz Markowski 	.ltr_tx_activity_timeout = WMI_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT,
596226a339bSBartosz Markowski 	.l1ss_enable = WMI_PDEV_PARAM_L1SS_ENABLE,
597226a339bSBartosz Markowski 	.dsleep_enable = WMI_PDEV_PARAM_DSLEEP_ENABLE,
598226a339bSBartosz Markowski 	.pcielp_txbuf_flush = WMI_PDEV_PARAM_PCIELP_TXBUF_FLUSH,
599226a339bSBartosz Markowski 	.pcielp_txbuf_watermark = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
600226a339bSBartosz Markowski 	.pcielp_txbuf_tmo_en = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
601226a339bSBartosz Markowski 	.pcielp_txbuf_tmo_value = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE,
602226a339bSBartosz Markowski 	.pdev_stats_update_period = WMI_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD,
603226a339bSBartosz Markowski 	.vdev_stats_update_period = WMI_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD,
604226a339bSBartosz Markowski 	.peer_stats_update_period = WMI_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD,
605226a339bSBartosz Markowski 	.bcnflt_stats_update_period = WMI_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
606226a339bSBartosz Markowski 	.pmf_qos = WMI_PDEV_PARAM_PMF_QOS,
607226a339bSBartosz Markowski 	.arp_ac_override = WMI_PDEV_PARAM_ARP_AC_OVERRIDE,
608226a339bSBartosz Markowski 	.dcs = WMI_PDEV_PARAM_DCS,
609226a339bSBartosz Markowski 	.ani_enable = WMI_PDEV_PARAM_ANI_ENABLE,
610226a339bSBartosz Markowski 	.ani_poll_period = WMI_PDEV_PARAM_ANI_POLL_PERIOD,
611226a339bSBartosz Markowski 	.ani_listen_period = WMI_PDEV_PARAM_ANI_LISTEN_PERIOD,
612226a339bSBartosz Markowski 	.ani_ofdm_level = WMI_PDEV_PARAM_ANI_OFDM_LEVEL,
613226a339bSBartosz Markowski 	.ani_cck_level = WMI_PDEV_PARAM_ANI_CCK_LEVEL,
614226a339bSBartosz Markowski 	.dyntxchain = WMI_PDEV_PARAM_DYNTXCHAIN,
615226a339bSBartosz Markowski 	.proxy_sta = WMI_PDEV_PARAM_PROXY_STA,
616226a339bSBartosz Markowski 	.idle_ps_config = WMI_PDEV_PARAM_IDLE_PS_CONFIG,
617226a339bSBartosz Markowski 	.power_gating_sleep = WMI_PDEV_PARAM_POWER_GATING_SLEEP,
618226a339bSBartosz Markowski 	.fast_channel_reset = WMI_PDEV_PARAM_UNSUPPORTED,
619226a339bSBartosz Markowski 	.burst_dur = WMI_PDEV_PARAM_UNSUPPORTED,
620226a339bSBartosz Markowski 	.burst_enable = WMI_PDEV_PARAM_UNSUPPORTED,
621a7bd3e99SPeter Oh 	.cal_period = WMI_PDEV_PARAM_UNSUPPORTED,
622226a339bSBartosz Markowski };
623226a339bSBartosz Markowski 
624226a339bSBartosz Markowski static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
625226a339bSBartosz Markowski 	.tx_chain_mask = WMI_10X_PDEV_PARAM_TX_CHAIN_MASK,
626226a339bSBartosz Markowski 	.rx_chain_mask = WMI_10X_PDEV_PARAM_RX_CHAIN_MASK,
627226a339bSBartosz Markowski 	.txpower_limit2g = WMI_10X_PDEV_PARAM_TXPOWER_LIMIT2G,
628226a339bSBartosz Markowski 	.txpower_limit5g = WMI_10X_PDEV_PARAM_TXPOWER_LIMIT5G,
629226a339bSBartosz Markowski 	.txpower_scale = WMI_10X_PDEV_PARAM_TXPOWER_SCALE,
630226a339bSBartosz Markowski 	.beacon_gen_mode = WMI_10X_PDEV_PARAM_BEACON_GEN_MODE,
631226a339bSBartosz Markowski 	.beacon_tx_mode = WMI_10X_PDEV_PARAM_BEACON_TX_MODE,
632226a339bSBartosz Markowski 	.resmgr_offchan_mode = WMI_10X_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
633226a339bSBartosz Markowski 	.protection_mode = WMI_10X_PDEV_PARAM_PROTECTION_MODE,
634226a339bSBartosz Markowski 	.dynamic_bw = WMI_10X_PDEV_PARAM_DYNAMIC_BW,
635226a339bSBartosz Markowski 	.non_agg_sw_retry_th = WMI_10X_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
636226a339bSBartosz Markowski 	.agg_sw_retry_th = WMI_10X_PDEV_PARAM_AGG_SW_RETRY_TH,
637226a339bSBartosz Markowski 	.sta_kickout_th = WMI_10X_PDEV_PARAM_STA_KICKOUT_TH,
638226a339bSBartosz Markowski 	.ac_aggrsize_scaling = WMI_10X_PDEV_PARAM_AC_AGGRSIZE_SCALING,
639226a339bSBartosz Markowski 	.ltr_enable = WMI_10X_PDEV_PARAM_LTR_ENABLE,
640226a339bSBartosz Markowski 	.ltr_ac_latency_be = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BE,
641226a339bSBartosz Markowski 	.ltr_ac_latency_bk = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BK,
642226a339bSBartosz Markowski 	.ltr_ac_latency_vi = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VI,
643226a339bSBartosz Markowski 	.ltr_ac_latency_vo = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VO,
644226a339bSBartosz Markowski 	.ltr_ac_latency_timeout = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT,
645226a339bSBartosz Markowski 	.ltr_sleep_override = WMI_10X_PDEV_PARAM_LTR_SLEEP_OVERRIDE,
646226a339bSBartosz Markowski 	.ltr_rx_override = WMI_10X_PDEV_PARAM_LTR_RX_OVERRIDE,
647226a339bSBartosz Markowski 	.ltr_tx_activity_timeout = WMI_10X_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT,
648226a339bSBartosz Markowski 	.l1ss_enable = WMI_10X_PDEV_PARAM_L1SS_ENABLE,
649226a339bSBartosz Markowski 	.dsleep_enable = WMI_10X_PDEV_PARAM_DSLEEP_ENABLE,
650226a339bSBartosz Markowski 	.pcielp_txbuf_flush = WMI_PDEV_PARAM_UNSUPPORTED,
651226a339bSBartosz Markowski 	.pcielp_txbuf_watermark = WMI_PDEV_PARAM_UNSUPPORTED,
652226a339bSBartosz Markowski 	.pcielp_txbuf_tmo_en = WMI_PDEV_PARAM_UNSUPPORTED,
653226a339bSBartosz Markowski 	.pcielp_txbuf_tmo_value = WMI_PDEV_PARAM_UNSUPPORTED,
654226a339bSBartosz Markowski 	.pdev_stats_update_period = WMI_10X_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD,
655226a339bSBartosz Markowski 	.vdev_stats_update_period = WMI_10X_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD,
656226a339bSBartosz Markowski 	.peer_stats_update_period = WMI_10X_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD,
657226a339bSBartosz Markowski 	.bcnflt_stats_update_period =
658226a339bSBartosz Markowski 				WMI_10X_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
659226a339bSBartosz Markowski 	.pmf_qos = WMI_10X_PDEV_PARAM_PMF_QOS,
660ab6258edSMarek Puzyniak 	.arp_ac_override = WMI_10X_PDEV_PARAM_ARPDHCP_AC_OVERRIDE,
661226a339bSBartosz Markowski 	.dcs = WMI_10X_PDEV_PARAM_DCS,
662226a339bSBartosz Markowski 	.ani_enable = WMI_10X_PDEV_PARAM_ANI_ENABLE,
663226a339bSBartosz Markowski 	.ani_poll_period = WMI_10X_PDEV_PARAM_ANI_POLL_PERIOD,
664226a339bSBartosz Markowski 	.ani_listen_period = WMI_10X_PDEV_PARAM_ANI_LISTEN_PERIOD,
665226a339bSBartosz Markowski 	.ani_ofdm_level = WMI_10X_PDEV_PARAM_ANI_OFDM_LEVEL,
666226a339bSBartosz Markowski 	.ani_cck_level = WMI_10X_PDEV_PARAM_ANI_CCK_LEVEL,
667226a339bSBartosz Markowski 	.dyntxchain = WMI_10X_PDEV_PARAM_DYNTXCHAIN,
668226a339bSBartosz Markowski 	.proxy_sta = WMI_PDEV_PARAM_UNSUPPORTED,
669226a339bSBartosz Markowski 	.idle_ps_config = WMI_PDEV_PARAM_UNSUPPORTED,
670226a339bSBartosz Markowski 	.power_gating_sleep = WMI_PDEV_PARAM_UNSUPPORTED,
671226a339bSBartosz Markowski 	.fast_channel_reset = WMI_10X_PDEV_PARAM_FAST_CHANNEL_RESET,
672226a339bSBartosz Markowski 	.burst_dur = WMI_10X_PDEV_PARAM_BURST_DUR,
673226a339bSBartosz Markowski 	.burst_enable = WMI_10X_PDEV_PARAM_BURST_ENABLE,
674a7bd3e99SPeter Oh 	.cal_period = WMI_10X_PDEV_PARAM_CAL_PERIOD,
675226a339bSBartosz Markowski };
676226a339bSBartosz Markowski 
6774a16fbecSRajkumar Manoharan static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
6784a16fbecSRajkumar Manoharan 	.tx_chain_mask = WMI_10X_PDEV_PARAM_TX_CHAIN_MASK,
6794a16fbecSRajkumar Manoharan 	.rx_chain_mask = WMI_10X_PDEV_PARAM_RX_CHAIN_MASK,
6804a16fbecSRajkumar Manoharan 	.txpower_limit2g = WMI_10X_PDEV_PARAM_TXPOWER_LIMIT2G,
6814a16fbecSRajkumar Manoharan 	.txpower_limit5g = WMI_10X_PDEV_PARAM_TXPOWER_LIMIT5G,
6824a16fbecSRajkumar Manoharan 	.txpower_scale = WMI_10X_PDEV_PARAM_TXPOWER_SCALE,
6834a16fbecSRajkumar Manoharan 	.beacon_gen_mode = WMI_10X_PDEV_PARAM_BEACON_GEN_MODE,
6844a16fbecSRajkumar Manoharan 	.beacon_tx_mode = WMI_10X_PDEV_PARAM_BEACON_TX_MODE,
6854a16fbecSRajkumar Manoharan 	.resmgr_offchan_mode = WMI_10X_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
6864a16fbecSRajkumar Manoharan 	.protection_mode = WMI_10X_PDEV_PARAM_PROTECTION_MODE,
6874a16fbecSRajkumar Manoharan 	.dynamic_bw = WMI_10X_PDEV_PARAM_DYNAMIC_BW,
6884a16fbecSRajkumar Manoharan 	.non_agg_sw_retry_th = WMI_10X_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
6894a16fbecSRajkumar Manoharan 	.agg_sw_retry_th = WMI_10X_PDEV_PARAM_AGG_SW_RETRY_TH,
6904a16fbecSRajkumar Manoharan 	.sta_kickout_th = WMI_10X_PDEV_PARAM_STA_KICKOUT_TH,
6914a16fbecSRajkumar Manoharan 	.ac_aggrsize_scaling = WMI_10X_PDEV_PARAM_AC_AGGRSIZE_SCALING,
6924a16fbecSRajkumar Manoharan 	.ltr_enable = WMI_10X_PDEV_PARAM_LTR_ENABLE,
6934a16fbecSRajkumar Manoharan 	.ltr_ac_latency_be = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BE,
6944a16fbecSRajkumar Manoharan 	.ltr_ac_latency_bk = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BK,
6954a16fbecSRajkumar Manoharan 	.ltr_ac_latency_vi = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VI,
6964a16fbecSRajkumar Manoharan 	.ltr_ac_latency_vo = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VO,
6974a16fbecSRajkumar Manoharan 	.ltr_ac_latency_timeout = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT,
6984a16fbecSRajkumar Manoharan 	.ltr_sleep_override = WMI_10X_PDEV_PARAM_LTR_SLEEP_OVERRIDE,
6994a16fbecSRajkumar Manoharan 	.ltr_rx_override = WMI_10X_PDEV_PARAM_LTR_RX_OVERRIDE,
7004a16fbecSRajkumar Manoharan 	.ltr_tx_activity_timeout = WMI_10X_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT,
7014a16fbecSRajkumar Manoharan 	.l1ss_enable = WMI_10X_PDEV_PARAM_L1SS_ENABLE,
7024a16fbecSRajkumar Manoharan 	.dsleep_enable = WMI_10X_PDEV_PARAM_DSLEEP_ENABLE,
7034a16fbecSRajkumar Manoharan 	.pcielp_txbuf_flush = WMI_PDEV_PARAM_UNSUPPORTED,
7044a16fbecSRajkumar Manoharan 	.pcielp_txbuf_watermark = WMI_PDEV_PARAM_UNSUPPORTED,
7054a16fbecSRajkumar Manoharan 	.pcielp_txbuf_tmo_en = WMI_PDEV_PARAM_UNSUPPORTED,
7064a16fbecSRajkumar Manoharan 	.pcielp_txbuf_tmo_value = WMI_PDEV_PARAM_UNSUPPORTED,
7074a16fbecSRajkumar Manoharan 	.pdev_stats_update_period = WMI_10X_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD,
7084a16fbecSRajkumar Manoharan 	.vdev_stats_update_period = WMI_10X_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD,
7094a16fbecSRajkumar Manoharan 	.peer_stats_update_period = WMI_10X_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD,
7104a16fbecSRajkumar Manoharan 	.bcnflt_stats_update_period =
7114a16fbecSRajkumar Manoharan 				WMI_10X_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
7124a16fbecSRajkumar Manoharan 	.pmf_qos = WMI_10X_PDEV_PARAM_PMF_QOS,
7134a16fbecSRajkumar Manoharan 	.arp_ac_override = WMI_10X_PDEV_PARAM_ARPDHCP_AC_OVERRIDE,
7144a16fbecSRajkumar Manoharan 	.dcs = WMI_10X_PDEV_PARAM_DCS,
7154a16fbecSRajkumar Manoharan 	.ani_enable = WMI_10X_PDEV_PARAM_ANI_ENABLE,
7164a16fbecSRajkumar Manoharan 	.ani_poll_period = WMI_10X_PDEV_PARAM_ANI_POLL_PERIOD,
7174a16fbecSRajkumar Manoharan 	.ani_listen_period = WMI_10X_PDEV_PARAM_ANI_LISTEN_PERIOD,
7184a16fbecSRajkumar Manoharan 	.ani_ofdm_level = WMI_10X_PDEV_PARAM_ANI_OFDM_LEVEL,
7194a16fbecSRajkumar Manoharan 	.ani_cck_level = WMI_10X_PDEV_PARAM_ANI_CCK_LEVEL,
7204a16fbecSRajkumar Manoharan 	.dyntxchain = WMI_10X_PDEV_PARAM_DYNTXCHAIN,
7214a16fbecSRajkumar Manoharan 	.proxy_sta = WMI_PDEV_PARAM_UNSUPPORTED,
7224a16fbecSRajkumar Manoharan 	.idle_ps_config = WMI_PDEV_PARAM_UNSUPPORTED,
7234a16fbecSRajkumar Manoharan 	.power_gating_sleep = WMI_PDEV_PARAM_UNSUPPORTED,
7244a16fbecSRajkumar Manoharan 	.fast_channel_reset = WMI_10X_PDEV_PARAM_FAST_CHANNEL_RESET,
7254a16fbecSRajkumar Manoharan 	.burst_dur = WMI_10X_PDEV_PARAM_BURST_DUR,
7264a16fbecSRajkumar Manoharan 	.burst_enable = WMI_10X_PDEV_PARAM_BURST_ENABLE,
7274a16fbecSRajkumar Manoharan 	.cal_period = WMI_10X_PDEV_PARAM_CAL_PERIOD,
7284a16fbecSRajkumar Manoharan };
7294a16fbecSRajkumar Manoharan 
73024c88f78SMichal Kazior /* firmware 10.2 specific mappings */
73124c88f78SMichal Kazior static struct wmi_cmd_map wmi_10_2_cmd_map = {
73224c88f78SMichal Kazior 	.init_cmdid = WMI_10_2_INIT_CMDID,
73324c88f78SMichal Kazior 	.start_scan_cmdid = WMI_10_2_START_SCAN_CMDID,
73424c88f78SMichal Kazior 	.stop_scan_cmdid = WMI_10_2_STOP_SCAN_CMDID,
73524c88f78SMichal Kazior 	.scan_chan_list_cmdid = WMI_10_2_SCAN_CHAN_LIST_CMDID,
73624c88f78SMichal Kazior 	.scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED,
73724c88f78SMichal Kazior 	.pdev_set_regdomain_cmdid = WMI_10_2_PDEV_SET_REGDOMAIN_CMDID,
73824c88f78SMichal Kazior 	.pdev_set_channel_cmdid = WMI_10_2_PDEV_SET_CHANNEL_CMDID,
73924c88f78SMichal Kazior 	.pdev_set_param_cmdid = WMI_10_2_PDEV_SET_PARAM_CMDID,
74024c88f78SMichal Kazior 	.pdev_pktlog_enable_cmdid = WMI_10_2_PDEV_PKTLOG_ENABLE_CMDID,
74124c88f78SMichal Kazior 	.pdev_pktlog_disable_cmdid = WMI_10_2_PDEV_PKTLOG_DISABLE_CMDID,
74224c88f78SMichal Kazior 	.pdev_set_wmm_params_cmdid = WMI_10_2_PDEV_SET_WMM_PARAMS_CMDID,
74324c88f78SMichal Kazior 	.pdev_set_ht_cap_ie_cmdid = WMI_10_2_PDEV_SET_HT_CAP_IE_CMDID,
74424c88f78SMichal Kazior 	.pdev_set_vht_cap_ie_cmdid = WMI_10_2_PDEV_SET_VHT_CAP_IE_CMDID,
74524c88f78SMichal Kazior 	.pdev_set_quiet_mode_cmdid = WMI_10_2_PDEV_SET_QUIET_MODE_CMDID,
74624c88f78SMichal Kazior 	.pdev_green_ap_ps_enable_cmdid = WMI_10_2_PDEV_GREEN_AP_PS_ENABLE_CMDID,
74724c88f78SMichal Kazior 	.pdev_get_tpc_config_cmdid = WMI_10_2_PDEV_GET_TPC_CONFIG_CMDID,
74824c88f78SMichal Kazior 	.pdev_set_base_macaddr_cmdid = WMI_10_2_PDEV_SET_BASE_MACADDR_CMDID,
74924c88f78SMichal Kazior 	.vdev_create_cmdid = WMI_10_2_VDEV_CREATE_CMDID,
75024c88f78SMichal Kazior 	.vdev_delete_cmdid = WMI_10_2_VDEV_DELETE_CMDID,
75124c88f78SMichal Kazior 	.vdev_start_request_cmdid = WMI_10_2_VDEV_START_REQUEST_CMDID,
75224c88f78SMichal Kazior 	.vdev_restart_request_cmdid = WMI_10_2_VDEV_RESTART_REQUEST_CMDID,
75324c88f78SMichal Kazior 	.vdev_up_cmdid = WMI_10_2_VDEV_UP_CMDID,
75424c88f78SMichal Kazior 	.vdev_stop_cmdid = WMI_10_2_VDEV_STOP_CMDID,
75524c88f78SMichal Kazior 	.vdev_down_cmdid = WMI_10_2_VDEV_DOWN_CMDID,
75624c88f78SMichal Kazior 	.vdev_set_param_cmdid = WMI_10_2_VDEV_SET_PARAM_CMDID,
75724c88f78SMichal Kazior 	.vdev_install_key_cmdid = WMI_10_2_VDEV_INSTALL_KEY_CMDID,
75824c88f78SMichal Kazior 	.peer_create_cmdid = WMI_10_2_PEER_CREATE_CMDID,
75924c88f78SMichal Kazior 	.peer_delete_cmdid = WMI_10_2_PEER_DELETE_CMDID,
76024c88f78SMichal Kazior 	.peer_flush_tids_cmdid = WMI_10_2_PEER_FLUSH_TIDS_CMDID,
76124c88f78SMichal Kazior 	.peer_set_param_cmdid = WMI_10_2_PEER_SET_PARAM_CMDID,
76224c88f78SMichal Kazior 	.peer_assoc_cmdid = WMI_10_2_PEER_ASSOC_CMDID,
76324c88f78SMichal Kazior 	.peer_add_wds_entry_cmdid = WMI_10_2_PEER_ADD_WDS_ENTRY_CMDID,
76424c88f78SMichal Kazior 	.peer_remove_wds_entry_cmdid = WMI_10_2_PEER_REMOVE_WDS_ENTRY_CMDID,
76524c88f78SMichal Kazior 	.peer_mcast_group_cmdid = WMI_10_2_PEER_MCAST_GROUP_CMDID,
76624c88f78SMichal Kazior 	.bcn_tx_cmdid = WMI_10_2_BCN_TX_CMDID,
76724c88f78SMichal Kazior 	.pdev_send_bcn_cmdid = WMI_10_2_PDEV_SEND_BCN_CMDID,
76824c88f78SMichal Kazior 	.bcn_tmpl_cmdid = WMI_CMD_UNSUPPORTED,
76924c88f78SMichal Kazior 	.bcn_filter_rx_cmdid = WMI_10_2_BCN_FILTER_RX_CMDID,
77024c88f78SMichal Kazior 	.prb_req_filter_rx_cmdid = WMI_10_2_PRB_REQ_FILTER_RX_CMDID,
77124c88f78SMichal Kazior 	.mgmt_tx_cmdid = WMI_10_2_MGMT_TX_CMDID,
77224c88f78SMichal Kazior 	.prb_tmpl_cmdid = WMI_CMD_UNSUPPORTED,
77324c88f78SMichal Kazior 	.addba_clear_resp_cmdid = WMI_10_2_ADDBA_CLEAR_RESP_CMDID,
77424c88f78SMichal Kazior 	.addba_send_cmdid = WMI_10_2_ADDBA_SEND_CMDID,
77524c88f78SMichal Kazior 	.addba_status_cmdid = WMI_10_2_ADDBA_STATUS_CMDID,
77624c88f78SMichal Kazior 	.delba_send_cmdid = WMI_10_2_DELBA_SEND_CMDID,
77724c88f78SMichal Kazior 	.addba_set_resp_cmdid = WMI_10_2_ADDBA_SET_RESP_CMDID,
77824c88f78SMichal Kazior 	.send_singleamsdu_cmdid = WMI_10_2_SEND_SINGLEAMSDU_CMDID,
77924c88f78SMichal Kazior 	.sta_powersave_mode_cmdid = WMI_10_2_STA_POWERSAVE_MODE_CMDID,
78024c88f78SMichal Kazior 	.sta_powersave_param_cmdid = WMI_10_2_STA_POWERSAVE_PARAM_CMDID,
78124c88f78SMichal Kazior 	.sta_mimo_ps_mode_cmdid = WMI_10_2_STA_MIMO_PS_MODE_CMDID,
78224c88f78SMichal Kazior 	.pdev_dfs_enable_cmdid = WMI_10_2_PDEV_DFS_ENABLE_CMDID,
78324c88f78SMichal Kazior 	.pdev_dfs_disable_cmdid = WMI_10_2_PDEV_DFS_DISABLE_CMDID,
78424c88f78SMichal Kazior 	.roam_scan_mode = WMI_10_2_ROAM_SCAN_MODE,
78524c88f78SMichal Kazior 	.roam_scan_rssi_threshold = WMI_10_2_ROAM_SCAN_RSSI_THRESHOLD,
78624c88f78SMichal Kazior 	.roam_scan_period = WMI_10_2_ROAM_SCAN_PERIOD,
78724c88f78SMichal Kazior 	.roam_scan_rssi_change_threshold =
78824c88f78SMichal Kazior 				WMI_10_2_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
78924c88f78SMichal Kazior 	.roam_ap_profile = WMI_10_2_ROAM_AP_PROFILE,
79024c88f78SMichal Kazior 	.ofl_scan_add_ap_profile = WMI_10_2_OFL_SCAN_ADD_AP_PROFILE,
79124c88f78SMichal Kazior 	.ofl_scan_remove_ap_profile = WMI_10_2_OFL_SCAN_REMOVE_AP_PROFILE,
79224c88f78SMichal Kazior 	.ofl_scan_period = WMI_10_2_OFL_SCAN_PERIOD,
79324c88f78SMichal Kazior 	.p2p_dev_set_device_info = WMI_10_2_P2P_DEV_SET_DEVICE_INFO,
79424c88f78SMichal Kazior 	.p2p_dev_set_discoverability = WMI_10_2_P2P_DEV_SET_DISCOVERABILITY,
79524c88f78SMichal Kazior 	.p2p_go_set_beacon_ie = WMI_10_2_P2P_GO_SET_BEACON_IE,
79624c88f78SMichal Kazior 	.p2p_go_set_probe_resp_ie = WMI_10_2_P2P_GO_SET_PROBE_RESP_IE,
79724c88f78SMichal Kazior 	.p2p_set_vendor_ie_data_cmdid = WMI_CMD_UNSUPPORTED,
79824c88f78SMichal Kazior 	.ap_ps_peer_param_cmdid = WMI_10_2_AP_PS_PEER_PARAM_CMDID,
79924c88f78SMichal Kazior 	.ap_ps_peer_uapsd_coex_cmdid = WMI_CMD_UNSUPPORTED,
80024c88f78SMichal Kazior 	.peer_rate_retry_sched_cmdid = WMI_10_2_PEER_RATE_RETRY_SCHED_CMDID,
80124c88f78SMichal Kazior 	.wlan_profile_trigger_cmdid = WMI_10_2_WLAN_PROFILE_TRIGGER_CMDID,
80224c88f78SMichal Kazior 	.wlan_profile_set_hist_intvl_cmdid =
80324c88f78SMichal Kazior 				WMI_10_2_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
80424c88f78SMichal Kazior 	.wlan_profile_get_profile_data_cmdid =
80524c88f78SMichal Kazior 				WMI_10_2_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
80624c88f78SMichal Kazior 	.wlan_profile_enable_profile_id_cmdid =
80724c88f78SMichal Kazior 				WMI_10_2_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
80824c88f78SMichal Kazior 	.wlan_profile_list_profile_id_cmdid =
80924c88f78SMichal Kazior 				WMI_10_2_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
81024c88f78SMichal Kazior 	.pdev_suspend_cmdid = WMI_10_2_PDEV_SUSPEND_CMDID,
81124c88f78SMichal Kazior 	.pdev_resume_cmdid = WMI_10_2_PDEV_RESUME_CMDID,
81224c88f78SMichal Kazior 	.add_bcn_filter_cmdid = WMI_10_2_ADD_BCN_FILTER_CMDID,
81324c88f78SMichal Kazior 	.rmv_bcn_filter_cmdid = WMI_10_2_RMV_BCN_FILTER_CMDID,
81424c88f78SMichal Kazior 	.wow_add_wake_pattern_cmdid = WMI_10_2_WOW_ADD_WAKE_PATTERN_CMDID,
81524c88f78SMichal Kazior 	.wow_del_wake_pattern_cmdid = WMI_10_2_WOW_DEL_WAKE_PATTERN_CMDID,
81624c88f78SMichal Kazior 	.wow_enable_disable_wake_event_cmdid =
81724c88f78SMichal Kazior 				WMI_10_2_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
81824c88f78SMichal Kazior 	.wow_enable_cmdid = WMI_10_2_WOW_ENABLE_CMDID,
81924c88f78SMichal Kazior 	.wow_hostwakeup_from_sleep_cmdid =
82024c88f78SMichal Kazior 				WMI_10_2_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
82124c88f78SMichal Kazior 	.rtt_measreq_cmdid = WMI_10_2_RTT_MEASREQ_CMDID,
82224c88f78SMichal Kazior 	.rtt_tsf_cmdid = WMI_10_2_RTT_TSF_CMDID,
82324c88f78SMichal Kazior 	.vdev_spectral_scan_configure_cmdid =
82424c88f78SMichal Kazior 				WMI_10_2_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID,
82524c88f78SMichal Kazior 	.vdev_spectral_scan_enable_cmdid =
82624c88f78SMichal Kazior 				WMI_10_2_VDEV_SPECTRAL_SCAN_ENABLE_CMDID,
82724c88f78SMichal Kazior 	.request_stats_cmdid = WMI_10_2_REQUEST_STATS_CMDID,
82824c88f78SMichal Kazior 	.set_arp_ns_offload_cmdid = WMI_CMD_UNSUPPORTED,
82924c88f78SMichal Kazior 	.network_list_offload_config_cmdid = WMI_CMD_UNSUPPORTED,
83024c88f78SMichal Kazior 	.gtk_offload_cmdid = WMI_CMD_UNSUPPORTED,
83124c88f78SMichal Kazior 	.csa_offload_enable_cmdid = WMI_CMD_UNSUPPORTED,
83224c88f78SMichal Kazior 	.csa_offload_chanswitch_cmdid = WMI_CMD_UNSUPPORTED,
83324c88f78SMichal Kazior 	.chatter_set_mode_cmdid = WMI_CMD_UNSUPPORTED,
83424c88f78SMichal Kazior 	.peer_tid_addba_cmdid = WMI_CMD_UNSUPPORTED,
83524c88f78SMichal Kazior 	.peer_tid_delba_cmdid = WMI_CMD_UNSUPPORTED,
83624c88f78SMichal Kazior 	.sta_dtim_ps_method_cmdid = WMI_CMD_UNSUPPORTED,
83724c88f78SMichal Kazior 	.sta_uapsd_auto_trig_cmdid = WMI_CMD_UNSUPPORTED,
83824c88f78SMichal Kazior 	.sta_keepalive_cmd = WMI_CMD_UNSUPPORTED,
83924c88f78SMichal Kazior 	.echo_cmdid = WMI_10_2_ECHO_CMDID,
84024c88f78SMichal Kazior 	.pdev_utf_cmdid = WMI_10_2_PDEV_UTF_CMDID,
84124c88f78SMichal Kazior 	.dbglog_cfg_cmdid = WMI_10_2_DBGLOG_CFG_CMDID,
84224c88f78SMichal Kazior 	.pdev_qvit_cmdid = WMI_10_2_PDEV_QVIT_CMDID,
84324c88f78SMichal Kazior 	.pdev_ftm_intg_cmdid = WMI_CMD_UNSUPPORTED,
84424c88f78SMichal Kazior 	.vdev_set_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
84524c88f78SMichal Kazior 	.vdev_get_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
84624c88f78SMichal Kazior 	.force_fw_hang_cmdid = WMI_CMD_UNSUPPORTED,
84724c88f78SMichal Kazior 	.gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID,
84824c88f78SMichal Kazior 	.gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
849a57a6a27SRajkumar Manoharan 	.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
85024c88f78SMichal Kazior };
85124c88f78SMichal Kazior 
8520226d602SMichal Kazior void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
8532d66721cSMichal Kazior 				const struct wmi_channel_arg *arg)
8542d66721cSMichal Kazior {
8552d66721cSMichal Kazior 	u32 flags = 0;
8562d66721cSMichal Kazior 
8572d66721cSMichal Kazior 	memset(ch, 0, sizeof(*ch));
8582d66721cSMichal Kazior 
8592d66721cSMichal Kazior 	if (arg->passive)
8602d66721cSMichal Kazior 		flags |= WMI_CHAN_FLAG_PASSIVE;
8612d66721cSMichal Kazior 	if (arg->allow_ibss)
8622d66721cSMichal Kazior 		flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED;
8632d66721cSMichal Kazior 	if (arg->allow_ht)
8642d66721cSMichal Kazior 		flags |= WMI_CHAN_FLAG_ALLOW_HT;
8652d66721cSMichal Kazior 	if (arg->allow_vht)
8662d66721cSMichal Kazior 		flags |= WMI_CHAN_FLAG_ALLOW_VHT;
8672d66721cSMichal Kazior 	if (arg->ht40plus)
8682d66721cSMichal Kazior 		flags |= WMI_CHAN_FLAG_HT40_PLUS;
8692d66721cSMichal Kazior 	if (arg->chan_radar)
8702d66721cSMichal Kazior 		flags |= WMI_CHAN_FLAG_DFS;
8712d66721cSMichal Kazior 
8722d66721cSMichal Kazior 	ch->mhz = __cpu_to_le32(arg->freq);
8732d66721cSMichal Kazior 	ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1);
8742d66721cSMichal Kazior 	ch->band_center_freq2 = 0;
8752d66721cSMichal Kazior 	ch->min_power = arg->min_power;
8762d66721cSMichal Kazior 	ch->max_power = arg->max_power;
8772d66721cSMichal Kazior 	ch->reg_power = arg->max_reg_power;
8782d66721cSMichal Kazior 	ch->antenna_max = arg->max_antenna_gain;
8792d66721cSMichal Kazior 
8802d66721cSMichal Kazior 	/* mode & flags share storage */
8812d66721cSMichal Kazior 	ch->mode = arg->mode;
8822d66721cSMichal Kazior 	ch->flags |= __cpu_to_le32(flags);
8832d66721cSMichal Kazior }
8842d66721cSMichal Kazior 
8855e3dd157SKalle Valo int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
8865e3dd157SKalle Valo {
8875e3dd157SKalle Valo 	int ret;
888af762c0bSKalle Valo 
8895e3dd157SKalle Valo 	ret = wait_for_completion_timeout(&ar->wmi.service_ready,
8905e3dd157SKalle Valo 					  WMI_SERVICE_READY_TIMEOUT_HZ);
8915e3dd157SKalle Valo 	return ret;
8925e3dd157SKalle Valo }
8935e3dd157SKalle Valo 
8945e3dd157SKalle Valo int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar)
8955e3dd157SKalle Valo {
8965e3dd157SKalle Valo 	int ret;
897af762c0bSKalle Valo 
8985e3dd157SKalle Valo 	ret = wait_for_completion_timeout(&ar->wmi.unified_ready,
8995e3dd157SKalle Valo 					  WMI_UNIFIED_READY_TIMEOUT_HZ);
9005e3dd157SKalle Valo 	return ret;
9015e3dd157SKalle Valo }
9025e3dd157SKalle Valo 
903666a73f3SKalle Valo struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len)
9045e3dd157SKalle Valo {
9055e3dd157SKalle Valo 	struct sk_buff *skb;
9065e3dd157SKalle Valo 	u32 round_len = roundup(len, 4);
9075e3dd157SKalle Valo 
9087aa7a72aSMichal Kazior 	skb = ath10k_htc_alloc_skb(ar, WMI_SKB_HEADROOM + round_len);
9095e3dd157SKalle Valo 	if (!skb)
9105e3dd157SKalle Valo 		return NULL;
9115e3dd157SKalle Valo 
9125e3dd157SKalle Valo 	skb_reserve(skb, WMI_SKB_HEADROOM);
9135e3dd157SKalle Valo 	if (!IS_ALIGNED((unsigned long)skb->data, 4))
9147aa7a72aSMichal Kazior 		ath10k_warn(ar, "Unaligned WMI skb\n");
9155e3dd157SKalle Valo 
9165e3dd157SKalle Valo 	skb_put(skb, round_len);
9175e3dd157SKalle Valo 	memset(skb->data, 0, round_len);
9185e3dd157SKalle Valo 
9195e3dd157SKalle Valo 	return skb;
9205e3dd157SKalle Valo }
9215e3dd157SKalle Valo 
9225e3dd157SKalle Valo static void ath10k_wmi_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
9235e3dd157SKalle Valo {
9245e3dd157SKalle Valo 	dev_kfree_skb(skb);
9255e3dd157SKalle Valo }
9265e3dd157SKalle Valo 
927d7579d12SMichal Kazior int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb,
928ce42870eSBartosz Markowski 			       u32 cmd_id)
9295e3dd157SKalle Valo {
9305e3dd157SKalle Valo 	struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
9315e3dd157SKalle Valo 	struct wmi_cmd_hdr *cmd_hdr;
932be8b3943SMichal Kazior 	int ret;
9335e3dd157SKalle Valo 	u32 cmd = 0;
9345e3dd157SKalle Valo 
9355e3dd157SKalle Valo 	if (skb_push(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
9365e3dd157SKalle Valo 		return -ENOMEM;
9375e3dd157SKalle Valo 
9385e3dd157SKalle Valo 	cmd |= SM(cmd_id, WMI_CMD_HDR_CMD_ID);
9395e3dd157SKalle Valo 
9405e3dd157SKalle Valo 	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
9415e3dd157SKalle Valo 	cmd_hdr->cmd_id = __cpu_to_le32(cmd);
9425e3dd157SKalle Valo 
9435e3dd157SKalle Valo 	memset(skb_cb, 0, sizeof(*skb_cb));
944be8b3943SMichal Kazior 	ret = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb);
945d35a6c18SMichal Kazior 	trace_ath10k_wmi_cmd(ar, cmd_id, skb->data, skb->len, ret);
9465e3dd157SKalle Valo 
947be8b3943SMichal Kazior 	if (ret)
948be8b3943SMichal Kazior 		goto err_pull;
9495e3dd157SKalle Valo 
9505e3dd157SKalle Valo 	return 0;
951be8b3943SMichal Kazior 
952be8b3943SMichal Kazior err_pull:
953be8b3943SMichal Kazior 	skb_pull(skb, sizeof(struct wmi_cmd_hdr));
954be8b3943SMichal Kazior 	return ret;
955be8b3943SMichal Kazior }
956be8b3943SMichal Kazior 
957ed54388aSMichal Kazior static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
958ed54388aSMichal Kazior {
959ed54388aSMichal Kazior 	int ret;
960ed54388aSMichal Kazior 
961ed54388aSMichal Kazior 	lockdep_assert_held(&arvif->ar->data_lock);
962ed54388aSMichal Kazior 
963ed54388aSMichal Kazior 	if (arvif->beacon == NULL)
964ed54388aSMichal Kazior 		return;
965ed54388aSMichal Kazior 
966748afc47SMichal Kazior 	if (arvif->beacon_sent)
967748afc47SMichal Kazior 		return;
968ed54388aSMichal Kazior 
969748afc47SMichal Kazior 	ret = ath10k_wmi_beacon_send_ref_nowait(arvif);
970ed54388aSMichal Kazior 	if (ret)
971ed54388aSMichal Kazior 		return;
972ed54388aSMichal Kazior 
973748afc47SMichal Kazior 	/* We need to retain the arvif->beacon reference for DMA unmapping and
974748afc47SMichal Kazior 	 * freeing the skbuff later. */
975748afc47SMichal Kazior 	arvif->beacon_sent = true;
976ed54388aSMichal Kazior }
977ed54388aSMichal Kazior 
978ed54388aSMichal Kazior static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac,
979ed54388aSMichal Kazior 				       struct ieee80211_vif *vif)
980ed54388aSMichal Kazior {
981ed54388aSMichal Kazior 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
982ed54388aSMichal Kazior 
983ed54388aSMichal Kazior 	ath10k_wmi_tx_beacon_nowait(arvif);
984ed54388aSMichal Kazior }
985ed54388aSMichal Kazior 
986ed54388aSMichal Kazior static void ath10k_wmi_tx_beacons_nowait(struct ath10k *ar)
987ed54388aSMichal Kazior {
988ed54388aSMichal Kazior 	spin_lock_bh(&ar->data_lock);
989ed54388aSMichal Kazior 	ieee80211_iterate_active_interfaces_atomic(ar->hw,
990ed54388aSMichal Kazior 						   IEEE80211_IFACE_ITER_NORMAL,
991ed54388aSMichal Kazior 						   ath10k_wmi_tx_beacons_iter,
992ed54388aSMichal Kazior 						   NULL);
993ed54388aSMichal Kazior 	spin_unlock_bh(&ar->data_lock);
994ed54388aSMichal Kazior }
995ed54388aSMichal Kazior 
99612acbc43SMichal Kazior static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar)
997be8b3943SMichal Kazior {
998ed54388aSMichal Kazior 	/* try to send pending beacons first. they take priority */
999ed54388aSMichal Kazior 	ath10k_wmi_tx_beacons_nowait(ar);
1000ed54388aSMichal Kazior 
1001be8b3943SMichal Kazior 	wake_up(&ar->wmi.tx_credits_wq);
1002be8b3943SMichal Kazior }
1003be8b3943SMichal Kazior 
1004666a73f3SKalle Valo int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
1005be8b3943SMichal Kazior {
100634957b25SBartosz Markowski 	int ret = -EOPNOTSUPP;
1007be8b3943SMichal Kazior 
100856b84287SKalle Valo 	might_sleep();
100956b84287SKalle Valo 
101034957b25SBartosz Markowski 	if (cmd_id == WMI_CMD_UNSUPPORTED) {
10117aa7a72aSMichal Kazior 		ath10k_warn(ar, "wmi command %d is not supported by firmware\n",
101255321559SBartosz Markowski 			    cmd_id);
101355321559SBartosz Markowski 		return ret;
101455321559SBartosz Markowski 	}
1015be8b3943SMichal Kazior 
1016be8b3943SMichal Kazior 	wait_event_timeout(ar->wmi.tx_credits_wq, ({
1017ed54388aSMichal Kazior 		/* try to send pending beacons first. they take priority */
1018ed54388aSMichal Kazior 		ath10k_wmi_tx_beacons_nowait(ar);
1019ed54388aSMichal Kazior 
1020be8b3943SMichal Kazior 		ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id);
10217962b0d8SMichal Kazior 
10227962b0d8SMichal Kazior 		if (ret && test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))
10237962b0d8SMichal Kazior 			ret = -ESHUTDOWN;
10247962b0d8SMichal Kazior 
1025be8b3943SMichal Kazior 		(ret != -EAGAIN);
1026be8b3943SMichal Kazior 	}), 3*HZ);
1027be8b3943SMichal Kazior 
1028be8b3943SMichal Kazior 	if (ret)
1029be8b3943SMichal Kazior 		dev_kfree_skb_any(skb);
1030be8b3943SMichal Kazior 
1031be8b3943SMichal Kazior 	return ret;
10325e3dd157SKalle Valo }
10335e3dd157SKalle Valo 
1034d7579d12SMichal Kazior static struct sk_buff *
1035d7579d12SMichal Kazior ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
10365e00d31aSBartosz Markowski {
10375e00d31aSBartosz Markowski 	struct wmi_mgmt_tx_cmd *cmd;
10385e00d31aSBartosz Markowski 	struct ieee80211_hdr *hdr;
1039d7579d12SMichal Kazior 	struct sk_buff *skb;
10405e00d31aSBartosz Markowski 	int len;
1041d7579d12SMichal Kazior 	u32 buf_len = msdu->len;
10425e00d31aSBartosz Markowski 	u16 fc;
10435e00d31aSBartosz Markowski 
1044d7579d12SMichal Kazior 	hdr = (struct ieee80211_hdr *)msdu->data;
10455e00d31aSBartosz Markowski 	fc = le16_to_cpu(hdr->frame_control);
10465e00d31aSBartosz Markowski 
10475e00d31aSBartosz Markowski 	if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
1048d7579d12SMichal Kazior 		return ERR_PTR(-EINVAL);
10495e00d31aSBartosz Markowski 
1050d7579d12SMichal Kazior 	len = sizeof(cmd->hdr) + msdu->len;
1051eeab266cSMarek Kwaczynski 
1052eeab266cSMarek Kwaczynski 	if ((ieee80211_is_action(hdr->frame_control) ||
1053eeab266cSMarek Kwaczynski 	     ieee80211_is_deauth(hdr->frame_control) ||
1054eeab266cSMarek Kwaczynski 	     ieee80211_is_disassoc(hdr->frame_control)) &&
1055eeab266cSMarek Kwaczynski 	     ieee80211_has_protected(hdr->frame_control)) {
1056eeab266cSMarek Kwaczynski 		len += IEEE80211_CCMP_MIC_LEN;
1057eeab266cSMarek Kwaczynski 		buf_len += IEEE80211_CCMP_MIC_LEN;
1058eeab266cSMarek Kwaczynski 	}
1059eeab266cSMarek Kwaczynski 
10605e00d31aSBartosz Markowski 	len = round_up(len, 4);
10615e00d31aSBartosz Markowski 
1062d7579d12SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
1063d7579d12SMichal Kazior 	if (!skb)
1064d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
10655e00d31aSBartosz Markowski 
1066d7579d12SMichal Kazior 	cmd = (struct wmi_mgmt_tx_cmd *)skb->data;
10675e00d31aSBartosz Markowski 
1068d7579d12SMichal Kazior 	cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(msdu)->vdev_id);
10695e00d31aSBartosz Markowski 	cmd->hdr.tx_rate = 0;
10705e00d31aSBartosz Markowski 	cmd->hdr.tx_power = 0;
1071eeab266cSMarek Kwaczynski 	cmd->hdr.buf_len = __cpu_to_le32(buf_len);
10725e00d31aSBartosz Markowski 
1073b25f32cbSKalle Valo 	ether_addr_copy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr));
1074d7579d12SMichal Kazior 	memcpy(cmd->buf, msdu->data, msdu->len);
10755e00d31aSBartosz Markowski 
10767aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n",
1077d7579d12SMichal Kazior 		   msdu, skb->len, fc & IEEE80211_FCTL_FTYPE,
10785e00d31aSBartosz Markowski 		   fc & IEEE80211_FCTL_STYPE);
10795ce8e7fdSRajkumar Manoharan 	trace_ath10k_tx_hdr(ar, skb->data, skb->len);
10805ce8e7fdSRajkumar Manoharan 	trace_ath10k_tx_payload(ar, skb->data, skb->len);
10815e00d31aSBartosz Markowski 
1082d7579d12SMichal Kazior 	return skb;
10835e00d31aSBartosz Markowski }
10845e00d31aSBartosz Markowski 
10855c81c7fdSMichal Kazior static void ath10k_wmi_event_scan_started(struct ath10k *ar)
10865c81c7fdSMichal Kazior {
10875c81c7fdSMichal Kazior 	lockdep_assert_held(&ar->data_lock);
10885c81c7fdSMichal Kazior 
10895c81c7fdSMichal Kazior 	switch (ar->scan.state) {
10905c81c7fdSMichal Kazior 	case ATH10K_SCAN_IDLE:
10915c81c7fdSMichal Kazior 	case ATH10K_SCAN_RUNNING:
10925c81c7fdSMichal Kazior 	case ATH10K_SCAN_ABORTING:
10937aa7a72aSMichal Kazior 		ath10k_warn(ar, "received scan started event in an invalid scan state: %s (%d)\n",
10945c81c7fdSMichal Kazior 			    ath10k_scan_state_str(ar->scan.state),
10955c81c7fdSMichal Kazior 			    ar->scan.state);
10965c81c7fdSMichal Kazior 		break;
10975c81c7fdSMichal Kazior 	case ATH10K_SCAN_STARTING:
10985c81c7fdSMichal Kazior 		ar->scan.state = ATH10K_SCAN_RUNNING;
10995c81c7fdSMichal Kazior 
11005c81c7fdSMichal Kazior 		if (ar->scan.is_roc)
11015c81c7fdSMichal Kazior 			ieee80211_ready_on_channel(ar->hw);
11025c81c7fdSMichal Kazior 
11035c81c7fdSMichal Kazior 		complete(&ar->scan.started);
11045c81c7fdSMichal Kazior 		break;
11055c81c7fdSMichal Kazior 	}
11065c81c7fdSMichal Kazior }
11075c81c7fdSMichal Kazior 
11085c81c7fdSMichal Kazior static void ath10k_wmi_event_scan_completed(struct ath10k *ar)
11095c81c7fdSMichal Kazior {
11105c81c7fdSMichal Kazior 	lockdep_assert_held(&ar->data_lock);
11115c81c7fdSMichal Kazior 
11125c81c7fdSMichal Kazior 	switch (ar->scan.state) {
11135c81c7fdSMichal Kazior 	case ATH10K_SCAN_IDLE:
11145c81c7fdSMichal Kazior 	case ATH10K_SCAN_STARTING:
11155c81c7fdSMichal Kazior 		/* One suspected reason scan can be completed while starting is
11165c81c7fdSMichal Kazior 		 * if firmware fails to deliver all scan events to the host,
11175c81c7fdSMichal Kazior 		 * e.g. when transport pipe is full. This has been observed
11185c81c7fdSMichal Kazior 		 * with spectral scan phyerr events starving wmi transport
11195c81c7fdSMichal Kazior 		 * pipe. In such case the "scan completed" event should be (and
11205c81c7fdSMichal Kazior 		 * is) ignored by the host as it may be just firmware's scan
11215c81c7fdSMichal Kazior 		 * state machine recovering.
11225c81c7fdSMichal Kazior 		 */
11237aa7a72aSMichal Kazior 		ath10k_warn(ar, "received scan completed event in an invalid scan state: %s (%d)\n",
11245c81c7fdSMichal Kazior 			    ath10k_scan_state_str(ar->scan.state),
11255c81c7fdSMichal Kazior 			    ar->scan.state);
11265c81c7fdSMichal Kazior 		break;
11275c81c7fdSMichal Kazior 	case ATH10K_SCAN_RUNNING:
11285c81c7fdSMichal Kazior 	case ATH10K_SCAN_ABORTING:
11295c81c7fdSMichal Kazior 		__ath10k_scan_finish(ar);
11305c81c7fdSMichal Kazior 		break;
11315c81c7fdSMichal Kazior 	}
11325c81c7fdSMichal Kazior }
11335c81c7fdSMichal Kazior 
11345c81c7fdSMichal Kazior static void ath10k_wmi_event_scan_bss_chan(struct ath10k *ar)
11355c81c7fdSMichal Kazior {
11365c81c7fdSMichal Kazior 	lockdep_assert_held(&ar->data_lock);
11375c81c7fdSMichal Kazior 
11385c81c7fdSMichal Kazior 	switch (ar->scan.state) {
11395c81c7fdSMichal Kazior 	case ATH10K_SCAN_IDLE:
11405c81c7fdSMichal Kazior 	case ATH10K_SCAN_STARTING:
11417aa7a72aSMichal Kazior 		ath10k_warn(ar, "received scan bss chan event in an invalid scan state: %s (%d)\n",
11425c81c7fdSMichal Kazior 			    ath10k_scan_state_str(ar->scan.state),
11435c81c7fdSMichal Kazior 			    ar->scan.state);
11445c81c7fdSMichal Kazior 		break;
11455c81c7fdSMichal Kazior 	case ATH10K_SCAN_RUNNING:
11465c81c7fdSMichal Kazior 	case ATH10K_SCAN_ABORTING:
11475c81c7fdSMichal Kazior 		ar->scan_channel = NULL;
11485c81c7fdSMichal Kazior 		break;
11495c81c7fdSMichal Kazior 	}
11505c81c7fdSMichal Kazior }
11515c81c7fdSMichal Kazior 
11525c81c7fdSMichal Kazior static void ath10k_wmi_event_scan_foreign_chan(struct ath10k *ar, u32 freq)
11535c81c7fdSMichal Kazior {
11545c81c7fdSMichal Kazior 	lockdep_assert_held(&ar->data_lock);
11555c81c7fdSMichal Kazior 
11565c81c7fdSMichal Kazior 	switch (ar->scan.state) {
11575c81c7fdSMichal Kazior 	case ATH10K_SCAN_IDLE:
11585c81c7fdSMichal Kazior 	case ATH10K_SCAN_STARTING:
11597aa7a72aSMichal Kazior 		ath10k_warn(ar, "received scan foreign chan event in an invalid scan state: %s (%d)\n",
11605c81c7fdSMichal Kazior 			    ath10k_scan_state_str(ar->scan.state),
11615c81c7fdSMichal Kazior 			    ar->scan.state);
11625c81c7fdSMichal Kazior 		break;
11635c81c7fdSMichal Kazior 	case ATH10K_SCAN_RUNNING:
11645c81c7fdSMichal Kazior 	case ATH10K_SCAN_ABORTING:
11655c81c7fdSMichal Kazior 		ar->scan_channel = ieee80211_get_channel(ar->hw->wiphy, freq);
11665c81c7fdSMichal Kazior 
11675c81c7fdSMichal Kazior 		if (ar->scan.is_roc && ar->scan.roc_freq == freq)
11685c81c7fdSMichal Kazior 			complete(&ar->scan.on_channel);
11695c81c7fdSMichal Kazior 		break;
11705c81c7fdSMichal Kazior 	}
11715c81c7fdSMichal Kazior }
11725c81c7fdSMichal Kazior 
11739ff8b724SMichal Kazior static const char *
11749ff8b724SMichal Kazior ath10k_wmi_event_scan_type_str(enum wmi_scan_event_type type,
11759ff8b724SMichal Kazior 			       enum wmi_scan_completion_reason reason)
11769ff8b724SMichal Kazior {
11779ff8b724SMichal Kazior 	switch (type) {
11789ff8b724SMichal Kazior 	case WMI_SCAN_EVENT_STARTED:
11799ff8b724SMichal Kazior 		return "started";
11809ff8b724SMichal Kazior 	case WMI_SCAN_EVENT_COMPLETED:
11819ff8b724SMichal Kazior 		switch (reason) {
11829ff8b724SMichal Kazior 		case WMI_SCAN_REASON_COMPLETED:
11839ff8b724SMichal Kazior 			return "completed";
11849ff8b724SMichal Kazior 		case WMI_SCAN_REASON_CANCELLED:
11859ff8b724SMichal Kazior 			return "completed [cancelled]";
11869ff8b724SMichal Kazior 		case WMI_SCAN_REASON_PREEMPTED:
11879ff8b724SMichal Kazior 			return "completed [preempted]";
11889ff8b724SMichal Kazior 		case WMI_SCAN_REASON_TIMEDOUT:
11899ff8b724SMichal Kazior 			return "completed [timedout]";
11909ff8b724SMichal Kazior 		case WMI_SCAN_REASON_MAX:
11919ff8b724SMichal Kazior 			break;
11929ff8b724SMichal Kazior 		}
11939ff8b724SMichal Kazior 		return "completed [unknown]";
11949ff8b724SMichal Kazior 	case WMI_SCAN_EVENT_BSS_CHANNEL:
11959ff8b724SMichal Kazior 		return "bss channel";
11969ff8b724SMichal Kazior 	case WMI_SCAN_EVENT_FOREIGN_CHANNEL:
11979ff8b724SMichal Kazior 		return "foreign channel";
11989ff8b724SMichal Kazior 	case WMI_SCAN_EVENT_DEQUEUED:
11999ff8b724SMichal Kazior 		return "dequeued";
12009ff8b724SMichal Kazior 	case WMI_SCAN_EVENT_PREEMPTED:
12019ff8b724SMichal Kazior 		return "preempted";
12029ff8b724SMichal Kazior 	case WMI_SCAN_EVENT_START_FAILED:
12039ff8b724SMichal Kazior 		return "start failed";
12049ff8b724SMichal Kazior 	default:
12059ff8b724SMichal Kazior 		return "unknown";
12069ff8b724SMichal Kazior 	}
12079ff8b724SMichal Kazior }
12089ff8b724SMichal Kazior 
1209d7579d12SMichal Kazior static int ath10k_wmi_op_pull_scan_ev(struct ath10k *ar, struct sk_buff *skb,
121032653cf1SMichal Kazior 				      struct wmi_scan_ev_arg *arg)
121132653cf1SMichal Kazior {
121232653cf1SMichal Kazior 	struct wmi_scan_event *ev = (void *)skb->data;
121332653cf1SMichal Kazior 
121432653cf1SMichal Kazior 	if (skb->len < sizeof(*ev))
121532653cf1SMichal Kazior 		return -EPROTO;
121632653cf1SMichal Kazior 
121732653cf1SMichal Kazior 	skb_pull(skb, sizeof(*ev));
121832653cf1SMichal Kazior 	arg->event_type = ev->event_type;
121932653cf1SMichal Kazior 	arg->reason = ev->reason;
122032653cf1SMichal Kazior 	arg->channel_freq = ev->channel_freq;
122132653cf1SMichal Kazior 	arg->scan_req_id = ev->scan_req_id;
122232653cf1SMichal Kazior 	arg->scan_id = ev->scan_id;
122332653cf1SMichal Kazior 	arg->vdev_id = ev->vdev_id;
122432653cf1SMichal Kazior 
122532653cf1SMichal Kazior 	return 0;
122632653cf1SMichal Kazior }
122732653cf1SMichal Kazior 
12280226d602SMichal Kazior int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
12295e3dd157SKalle Valo {
123032653cf1SMichal Kazior 	struct wmi_scan_ev_arg arg = {};
12315e3dd157SKalle Valo 	enum wmi_scan_event_type event_type;
12325e3dd157SKalle Valo 	enum wmi_scan_completion_reason reason;
12335e3dd157SKalle Valo 	u32 freq;
12345e3dd157SKalle Valo 	u32 req_id;
12355e3dd157SKalle Valo 	u32 scan_id;
12365e3dd157SKalle Valo 	u32 vdev_id;
123732653cf1SMichal Kazior 	int ret;
12385e3dd157SKalle Valo 
1239d7579d12SMichal Kazior 	ret = ath10k_wmi_pull_scan(ar, skb, &arg);
124032653cf1SMichal Kazior 	if (ret) {
124132653cf1SMichal Kazior 		ath10k_warn(ar, "failed to parse scan event: %d\n", ret);
124232653cf1SMichal Kazior 		return ret;
124332653cf1SMichal Kazior 	}
124432653cf1SMichal Kazior 
124532653cf1SMichal Kazior 	event_type = __le32_to_cpu(arg.event_type);
124632653cf1SMichal Kazior 	reason = __le32_to_cpu(arg.reason);
124732653cf1SMichal Kazior 	freq = __le32_to_cpu(arg.channel_freq);
124832653cf1SMichal Kazior 	req_id = __le32_to_cpu(arg.scan_req_id);
124932653cf1SMichal Kazior 	scan_id = __le32_to_cpu(arg.scan_id);
125032653cf1SMichal Kazior 	vdev_id = __le32_to_cpu(arg.vdev_id);
12515e3dd157SKalle Valo 
12525e3dd157SKalle Valo 	spin_lock_bh(&ar->data_lock);
12535e3dd157SKalle Valo 
12547aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
12555c81c7fdSMichal Kazior 		   "scan event %s type %d reason %d freq %d req_id %d scan_id %d vdev_id %d state %s (%d)\n",
12565c81c7fdSMichal Kazior 		   ath10k_wmi_event_scan_type_str(event_type, reason),
12575c81c7fdSMichal Kazior 		   event_type, reason, freq, req_id, scan_id, vdev_id,
12585c81c7fdSMichal Kazior 		   ath10k_scan_state_str(ar->scan.state), ar->scan.state);
12595c81c7fdSMichal Kazior 
12605e3dd157SKalle Valo 	switch (event_type) {
12615e3dd157SKalle Valo 	case WMI_SCAN_EVENT_STARTED:
12625c81c7fdSMichal Kazior 		ath10k_wmi_event_scan_started(ar);
12635e3dd157SKalle Valo 		break;
12645e3dd157SKalle Valo 	case WMI_SCAN_EVENT_COMPLETED:
12655c81c7fdSMichal Kazior 		ath10k_wmi_event_scan_completed(ar);
12665e3dd157SKalle Valo 		break;
12675e3dd157SKalle Valo 	case WMI_SCAN_EVENT_BSS_CHANNEL:
12685c81c7fdSMichal Kazior 		ath10k_wmi_event_scan_bss_chan(ar);
12695e3dd157SKalle Valo 		break;
12705e3dd157SKalle Valo 	case WMI_SCAN_EVENT_FOREIGN_CHANNEL:
12715c81c7fdSMichal Kazior 		ath10k_wmi_event_scan_foreign_chan(ar, freq);
12725c81c7fdSMichal Kazior 		break;
12735c81c7fdSMichal Kazior 	case WMI_SCAN_EVENT_START_FAILED:
12747aa7a72aSMichal Kazior 		ath10k_warn(ar, "received scan start failure event\n");
12755e3dd157SKalle Valo 		break;
12765e3dd157SKalle Valo 	case WMI_SCAN_EVENT_DEQUEUED:
12775e3dd157SKalle Valo 	case WMI_SCAN_EVENT_PREEMPTED:
12785e3dd157SKalle Valo 	default:
12795e3dd157SKalle Valo 		break;
12805e3dd157SKalle Valo 	}
12815e3dd157SKalle Valo 
12825e3dd157SKalle Valo 	spin_unlock_bh(&ar->data_lock);
12835e3dd157SKalle Valo 	return 0;
12845e3dd157SKalle Valo }
12855e3dd157SKalle Valo 
12865e3dd157SKalle Valo static inline enum ieee80211_band phy_mode_to_band(u32 phy_mode)
12875e3dd157SKalle Valo {
12885e3dd157SKalle Valo 	enum ieee80211_band band;
12895e3dd157SKalle Valo 
12905e3dd157SKalle Valo 	switch (phy_mode) {
12915e3dd157SKalle Valo 	case MODE_11A:
12925e3dd157SKalle Valo 	case MODE_11NA_HT20:
12935e3dd157SKalle Valo 	case MODE_11NA_HT40:
12945e3dd157SKalle Valo 	case MODE_11AC_VHT20:
12955e3dd157SKalle Valo 	case MODE_11AC_VHT40:
12965e3dd157SKalle Valo 	case MODE_11AC_VHT80:
12975e3dd157SKalle Valo 		band = IEEE80211_BAND_5GHZ;
12985e3dd157SKalle Valo 		break;
12995e3dd157SKalle Valo 	case MODE_11G:
13005e3dd157SKalle Valo 	case MODE_11B:
13015e3dd157SKalle Valo 	case MODE_11GONLY:
13025e3dd157SKalle Valo 	case MODE_11NG_HT20:
13035e3dd157SKalle Valo 	case MODE_11NG_HT40:
13045e3dd157SKalle Valo 	case MODE_11AC_VHT20_2G:
13055e3dd157SKalle Valo 	case MODE_11AC_VHT40_2G:
13065e3dd157SKalle Valo 	case MODE_11AC_VHT80_2G:
13075e3dd157SKalle Valo 	default:
13085e3dd157SKalle Valo 		band = IEEE80211_BAND_2GHZ;
13095e3dd157SKalle Valo 	}
13105e3dd157SKalle Valo 
13115e3dd157SKalle Valo 	return band;
13125e3dd157SKalle Valo }
13135e3dd157SKalle Valo 
13145e3dd157SKalle Valo static inline u8 get_rate_idx(u32 rate, enum ieee80211_band band)
13155e3dd157SKalle Valo {
13165e3dd157SKalle Valo 	u8 rate_idx = 0;
13175e3dd157SKalle Valo 
13185e3dd157SKalle Valo 	/* rate in Kbps */
13195e3dd157SKalle Valo 	switch (rate) {
13205e3dd157SKalle Valo 	case 1000:
13215e3dd157SKalle Valo 		rate_idx = 0;
13225e3dd157SKalle Valo 		break;
13235e3dd157SKalle Valo 	case 2000:
13245e3dd157SKalle Valo 		rate_idx = 1;
13255e3dd157SKalle Valo 		break;
13265e3dd157SKalle Valo 	case 5500:
13275e3dd157SKalle Valo 		rate_idx = 2;
13285e3dd157SKalle Valo 		break;
13295e3dd157SKalle Valo 	case 11000:
13305e3dd157SKalle Valo 		rate_idx = 3;
13315e3dd157SKalle Valo 		break;
13325e3dd157SKalle Valo 	case 6000:
13335e3dd157SKalle Valo 		rate_idx = 4;
13345e3dd157SKalle Valo 		break;
13355e3dd157SKalle Valo 	case 9000:
13365e3dd157SKalle Valo 		rate_idx = 5;
13375e3dd157SKalle Valo 		break;
13385e3dd157SKalle Valo 	case 12000:
13395e3dd157SKalle Valo 		rate_idx = 6;
13405e3dd157SKalle Valo 		break;
13415e3dd157SKalle Valo 	case 18000:
13425e3dd157SKalle Valo 		rate_idx = 7;
13435e3dd157SKalle Valo 		break;
13445e3dd157SKalle Valo 	case 24000:
13455e3dd157SKalle Valo 		rate_idx = 8;
13465e3dd157SKalle Valo 		break;
13475e3dd157SKalle Valo 	case 36000:
13485e3dd157SKalle Valo 		rate_idx = 9;
13495e3dd157SKalle Valo 		break;
13505e3dd157SKalle Valo 	case 48000:
13515e3dd157SKalle Valo 		rate_idx = 10;
13525e3dd157SKalle Valo 		break;
13535e3dd157SKalle Valo 	case 54000:
13545e3dd157SKalle Valo 		rate_idx = 11;
13555e3dd157SKalle Valo 		break;
13565e3dd157SKalle Valo 	default:
13575e3dd157SKalle Valo 		break;
13585e3dd157SKalle Valo 	}
13595e3dd157SKalle Valo 
13605e3dd157SKalle Valo 	if (band == IEEE80211_BAND_5GHZ) {
13615e3dd157SKalle Valo 		if (rate_idx > 3)
13625e3dd157SKalle Valo 			/* Omit CCK rates */
13635e3dd157SKalle Valo 			rate_idx -= 4;
13645e3dd157SKalle Valo 		else
13655e3dd157SKalle Valo 			rate_idx = 0;
13665e3dd157SKalle Valo 	}
13675e3dd157SKalle Valo 
13685e3dd157SKalle Valo 	return rate_idx;
13695e3dd157SKalle Valo }
13705e3dd157SKalle Valo 
1371504f6cdfSSujith Manoharan /* If keys are configured, HW decrypts all frames
1372504f6cdfSSujith Manoharan  * with protected bit set. Mark such frames as decrypted.
1373504f6cdfSSujith Manoharan  */
1374504f6cdfSSujith Manoharan static void ath10k_wmi_handle_wep_reauth(struct ath10k *ar,
1375504f6cdfSSujith Manoharan 					 struct sk_buff *skb,
1376504f6cdfSSujith Manoharan 					 struct ieee80211_rx_status *status)
1377504f6cdfSSujith Manoharan {
1378504f6cdfSSujith Manoharan 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1379504f6cdfSSujith Manoharan 	unsigned int hdrlen;
1380504f6cdfSSujith Manoharan 	bool peer_key;
1381504f6cdfSSujith Manoharan 	u8 *addr, keyidx;
1382504f6cdfSSujith Manoharan 
1383504f6cdfSSujith Manoharan 	if (!ieee80211_is_auth(hdr->frame_control) ||
1384504f6cdfSSujith Manoharan 	    !ieee80211_has_protected(hdr->frame_control))
1385504f6cdfSSujith Manoharan 		return;
1386504f6cdfSSujith Manoharan 
1387504f6cdfSSujith Manoharan 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
1388504f6cdfSSujith Manoharan 	if (skb->len < (hdrlen + IEEE80211_WEP_IV_LEN))
1389504f6cdfSSujith Manoharan 		return;
1390504f6cdfSSujith Manoharan 
1391504f6cdfSSujith Manoharan 	keyidx = skb->data[hdrlen + (IEEE80211_WEP_IV_LEN - 1)] >> WEP_KEYID_SHIFT;
1392504f6cdfSSujith Manoharan 	addr = ieee80211_get_SA(hdr);
1393504f6cdfSSujith Manoharan 
1394504f6cdfSSujith Manoharan 	spin_lock_bh(&ar->data_lock);
1395504f6cdfSSujith Manoharan 	peer_key = ath10k_mac_is_peer_wep_key_set(ar, addr, keyidx);
1396504f6cdfSSujith Manoharan 	spin_unlock_bh(&ar->data_lock);
1397504f6cdfSSujith Manoharan 
1398504f6cdfSSujith Manoharan 	if (peer_key) {
1399504f6cdfSSujith Manoharan 		ath10k_dbg(ar, ATH10K_DBG_MAC,
1400504f6cdfSSujith Manoharan 			   "mac wep key present for peer %pM\n", addr);
1401504f6cdfSSujith Manoharan 		status->flag |= RX_FLAG_DECRYPTED;
1402504f6cdfSSujith Manoharan 	}
1403504f6cdfSSujith Manoharan }
1404504f6cdfSSujith Manoharan 
1405d7579d12SMichal Kazior static int ath10k_wmi_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb,
1406d7579d12SMichal Kazior 					 struct wmi_mgmt_rx_ev_arg *arg)
14075e3dd157SKalle Valo {
14080d9b0438SMichal Kazior 	struct wmi_mgmt_rx_event_v1 *ev_v1;
14090d9b0438SMichal Kazior 	struct wmi_mgmt_rx_event_v2 *ev_v2;
14100d9b0438SMichal Kazior 	struct wmi_mgmt_rx_hdr_v1 *ev_hdr;
141132653cf1SMichal Kazior 	size_t pull_len;
141232653cf1SMichal Kazior 	u32 msdu_len;
14135e3dd157SKalle Valo 
14140d9b0438SMichal Kazior 	if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) {
14150d9b0438SMichal Kazior 		ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data;
14160d9b0438SMichal Kazior 		ev_hdr = &ev_v2->hdr.v1;
14170d9b0438SMichal Kazior 		pull_len = sizeof(*ev_v2);
14180d9b0438SMichal Kazior 	} else {
14190d9b0438SMichal Kazior 		ev_v1 = (struct wmi_mgmt_rx_event_v1 *)skb->data;
14200d9b0438SMichal Kazior 		ev_hdr = &ev_v1->hdr;
14210d9b0438SMichal Kazior 		pull_len = sizeof(*ev_v1);
14220d9b0438SMichal Kazior 	}
14230d9b0438SMichal Kazior 
142432653cf1SMichal Kazior 	if (skb->len < pull_len)
142532653cf1SMichal Kazior 		return -EPROTO;
142632653cf1SMichal Kazior 
142732653cf1SMichal Kazior 	skb_pull(skb, pull_len);
142832653cf1SMichal Kazior 	arg->channel = ev_hdr->channel;
142932653cf1SMichal Kazior 	arg->buf_len = ev_hdr->buf_len;
143032653cf1SMichal Kazior 	arg->status = ev_hdr->status;
143132653cf1SMichal Kazior 	arg->snr = ev_hdr->snr;
143232653cf1SMichal Kazior 	arg->phy_mode = ev_hdr->phy_mode;
143332653cf1SMichal Kazior 	arg->rate = ev_hdr->rate;
143432653cf1SMichal Kazior 
143532653cf1SMichal Kazior 	msdu_len = __le32_to_cpu(arg->buf_len);
143632653cf1SMichal Kazior 	if (skb->len < msdu_len)
143732653cf1SMichal Kazior 		return -EPROTO;
143832653cf1SMichal Kazior 
143932653cf1SMichal Kazior 	/* the WMI buffer might've ended up being padded to 4 bytes due to HTC
144032653cf1SMichal Kazior 	 * trailer with credit update. Trim the excess garbage.
144132653cf1SMichal Kazior 	 */
144232653cf1SMichal Kazior 	skb_trim(skb, msdu_len);
144332653cf1SMichal Kazior 
144432653cf1SMichal Kazior 	return 0;
144532653cf1SMichal Kazior }
144632653cf1SMichal Kazior 
14470226d602SMichal Kazior int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
144832653cf1SMichal Kazior {
144932653cf1SMichal Kazior 	struct wmi_mgmt_rx_ev_arg arg = {};
145032653cf1SMichal Kazior 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
145132653cf1SMichal Kazior 	struct ieee80211_hdr *hdr;
145232653cf1SMichal Kazior 	u32 rx_status;
145332653cf1SMichal Kazior 	u32 channel;
145432653cf1SMichal Kazior 	u32 phy_mode;
145532653cf1SMichal Kazior 	u32 snr;
145632653cf1SMichal Kazior 	u32 rate;
145732653cf1SMichal Kazior 	u32 buf_len;
145832653cf1SMichal Kazior 	u16 fc;
145932653cf1SMichal Kazior 	int ret;
146032653cf1SMichal Kazior 
1461d7579d12SMichal Kazior 	ret = ath10k_wmi_pull_mgmt_rx(ar, skb, &arg);
146232653cf1SMichal Kazior 	if (ret) {
146332653cf1SMichal Kazior 		ath10k_warn(ar, "failed to parse mgmt rx event: %d\n", ret);
146432653cf1SMichal Kazior 		return ret;
146532653cf1SMichal Kazior 	}
146632653cf1SMichal Kazior 
146732653cf1SMichal Kazior 	channel = __le32_to_cpu(arg.channel);
146832653cf1SMichal Kazior 	buf_len = __le32_to_cpu(arg.buf_len);
146932653cf1SMichal Kazior 	rx_status = __le32_to_cpu(arg.status);
147032653cf1SMichal Kazior 	snr = __le32_to_cpu(arg.snr);
147132653cf1SMichal Kazior 	phy_mode = __le32_to_cpu(arg.phy_mode);
147232653cf1SMichal Kazior 	rate = __le32_to_cpu(arg.rate);
14735e3dd157SKalle Valo 
14745e3dd157SKalle Valo 	memset(status, 0, sizeof(*status));
14755e3dd157SKalle Valo 
14767aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_MGMT,
14775e3dd157SKalle Valo 		   "event mgmt rx status %08x\n", rx_status);
14785e3dd157SKalle Valo 
1479e8a50f8bSMarek Puzyniak 	if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) {
1480e8a50f8bSMarek Puzyniak 		dev_kfree_skb(skb);
1481e8a50f8bSMarek Puzyniak 		return 0;
1482e8a50f8bSMarek Puzyniak 	}
1483e8a50f8bSMarek Puzyniak 
14845e3dd157SKalle Valo 	if (rx_status & WMI_RX_STATUS_ERR_DECRYPT) {
14855e3dd157SKalle Valo 		dev_kfree_skb(skb);
14865e3dd157SKalle Valo 		return 0;
14875e3dd157SKalle Valo 	}
14885e3dd157SKalle Valo 
14895e3dd157SKalle Valo 	if (rx_status & WMI_RX_STATUS_ERR_KEY_CACHE_MISS) {
14905e3dd157SKalle Valo 		dev_kfree_skb(skb);
14915e3dd157SKalle Valo 		return 0;
14925e3dd157SKalle Valo 	}
14935e3dd157SKalle Valo 
1494d67d0a02SMichal Kazior 	if (rx_status & WMI_RX_STATUS_ERR_CRC) {
1495d67d0a02SMichal Kazior 		dev_kfree_skb(skb);
1496d67d0a02SMichal Kazior 		return 0;
1497d67d0a02SMichal Kazior 	}
1498d67d0a02SMichal Kazior 
14995e3dd157SKalle Valo 	if (rx_status & WMI_RX_STATUS_ERR_MIC)
15005e3dd157SKalle Valo 		status->flag |= RX_FLAG_MMIC_ERROR;
15015e3dd157SKalle Valo 
150221040bf9SMichal Kazior 	/* Hardware can Rx CCK rates on 5GHz. In that case phy_mode is set to
1503453cdb61SMichal Kazior 	 * MODE_11B. This means phy_mode is not a reliable source for the band
150421040bf9SMichal Kazior 	 * of mgmt rx.
150521040bf9SMichal Kazior 	 */
150621040bf9SMichal Kazior 	if (channel >= 1 && channel <= 14) {
150721040bf9SMichal Kazior 		status->band = IEEE80211_BAND_2GHZ;
150821040bf9SMichal Kazior 	} else if (channel >= 36 && channel <= 165) {
150921040bf9SMichal Kazior 		status->band = IEEE80211_BAND_5GHZ;
1510453cdb61SMichal Kazior 	} else {
151121040bf9SMichal Kazior 		/* Shouldn't happen unless list of advertised channels to
151221040bf9SMichal Kazior 		 * mac80211 has been changed.
151321040bf9SMichal Kazior 		 */
151421040bf9SMichal Kazior 		WARN_ON_ONCE(1);
151521040bf9SMichal Kazior 		dev_kfree_skb(skb);
151621040bf9SMichal Kazior 		return 0;
1517453cdb61SMichal Kazior 	}
1518453cdb61SMichal Kazior 
151921040bf9SMichal Kazior 	if (phy_mode == MODE_11B && status->band == IEEE80211_BAND_5GHZ)
152021040bf9SMichal Kazior 		ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n");
152121040bf9SMichal Kazior 
15225e3dd157SKalle Valo 	status->freq = ieee80211_channel_to_frequency(channel, status->band);
15235e3dd157SKalle Valo 	status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR;
15245e3dd157SKalle Valo 	status->rate_idx = get_rate_idx(rate, status->band);
15255e3dd157SKalle Valo 
15265e3dd157SKalle Valo 	hdr = (struct ieee80211_hdr *)skb->data;
15275e3dd157SKalle Valo 	fc = le16_to_cpu(hdr->frame_control);
15285e3dd157SKalle Valo 
1529504f6cdfSSujith Manoharan 	ath10k_wmi_handle_wep_reauth(ar, skb, status);
1530504f6cdfSSujith Manoharan 
15312b6a6a90SMichal Kazior 	/* FW delivers WEP Shared Auth frame with Protected Bit set and
15322b6a6a90SMichal Kazior 	 * encrypted payload. However in case of PMF it delivers decrypted
15332b6a6a90SMichal Kazior 	 * frames with Protected Bit set. */
15342b6a6a90SMichal Kazior 	if (ieee80211_has_protected(hdr->frame_control) &&
15352b6a6a90SMichal Kazior 	    !ieee80211_is_auth(hdr->frame_control)) {
1536eeab266cSMarek Kwaczynski 		status->flag |= RX_FLAG_DECRYPTED;
1537eeab266cSMarek Kwaczynski 
1538eeab266cSMarek Kwaczynski 		if (!ieee80211_is_action(hdr->frame_control) &&
1539eeab266cSMarek Kwaczynski 		    !ieee80211_is_deauth(hdr->frame_control) &&
1540eeab266cSMarek Kwaczynski 		    !ieee80211_is_disassoc(hdr->frame_control)) {
1541eeab266cSMarek Kwaczynski 			status->flag |= RX_FLAG_IV_STRIPPED |
15425e3dd157SKalle Valo 					RX_FLAG_MMIC_STRIPPED;
15435e3dd157SKalle Valo 			hdr->frame_control = __cpu_to_le16(fc &
15445e3dd157SKalle Valo 					~IEEE80211_FCTL_PROTECTED);
15455e3dd157SKalle Valo 		}
1546eeab266cSMarek Kwaczynski 	}
15475e3dd157SKalle Valo 
15487aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_MGMT,
15495e3dd157SKalle Valo 		   "event mgmt rx skb %p len %d ftype %02x stype %02x\n",
15505e3dd157SKalle Valo 		   skb, skb->len,
15515e3dd157SKalle Valo 		   fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE);
15525e3dd157SKalle Valo 
15537aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_MGMT,
15545e3dd157SKalle Valo 		   "event mgmt rx freq %d band %d snr %d, rate_idx %d\n",
15555e3dd157SKalle Valo 		   status->freq, status->band, status->signal,
15565e3dd157SKalle Valo 		   status->rate_idx);
15575e3dd157SKalle Valo 
15585e3dd157SKalle Valo 	ieee80211_rx(ar->hw, skb);
15595e3dd157SKalle Valo 	return 0;
15605e3dd157SKalle Valo }
15615e3dd157SKalle Valo 
15622e1dea40SMichal Kazior static int freq_to_idx(struct ath10k *ar, int freq)
15632e1dea40SMichal Kazior {
15642e1dea40SMichal Kazior 	struct ieee80211_supported_band *sband;
15652e1dea40SMichal Kazior 	int band, ch, idx = 0;
15662e1dea40SMichal Kazior 
15672e1dea40SMichal Kazior 	for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) {
15682e1dea40SMichal Kazior 		sband = ar->hw->wiphy->bands[band];
15692e1dea40SMichal Kazior 		if (!sband)
15702e1dea40SMichal Kazior 			continue;
15712e1dea40SMichal Kazior 
15722e1dea40SMichal Kazior 		for (ch = 0; ch < sband->n_channels; ch++, idx++)
15732e1dea40SMichal Kazior 			if (sband->channels[ch].center_freq == freq)
15742e1dea40SMichal Kazior 				goto exit;
15752e1dea40SMichal Kazior 	}
15762e1dea40SMichal Kazior 
15772e1dea40SMichal Kazior exit:
15782e1dea40SMichal Kazior 	return idx;
15792e1dea40SMichal Kazior }
15802e1dea40SMichal Kazior 
1581d7579d12SMichal Kazior static int ath10k_wmi_op_pull_ch_info_ev(struct ath10k *ar, struct sk_buff *skb,
158232653cf1SMichal Kazior 					 struct wmi_ch_info_ev_arg *arg)
158332653cf1SMichal Kazior {
158432653cf1SMichal Kazior 	struct wmi_chan_info_event *ev = (void *)skb->data;
158532653cf1SMichal Kazior 
158632653cf1SMichal Kazior 	if (skb->len < sizeof(*ev))
158732653cf1SMichal Kazior 		return -EPROTO;
158832653cf1SMichal Kazior 
158932653cf1SMichal Kazior 	skb_pull(skb, sizeof(*ev));
159032653cf1SMichal Kazior 	arg->err_code = ev->err_code;
159132653cf1SMichal Kazior 	arg->freq = ev->freq;
159232653cf1SMichal Kazior 	arg->cmd_flags = ev->cmd_flags;
159332653cf1SMichal Kazior 	arg->noise_floor = ev->noise_floor;
159432653cf1SMichal Kazior 	arg->rx_clear_count = ev->rx_clear_count;
159532653cf1SMichal Kazior 	arg->cycle_count = ev->cycle_count;
159632653cf1SMichal Kazior 
159732653cf1SMichal Kazior 	return 0;
159832653cf1SMichal Kazior }
159932653cf1SMichal Kazior 
16000226d602SMichal Kazior void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb)
16015e3dd157SKalle Valo {
160232653cf1SMichal Kazior 	struct wmi_ch_info_ev_arg arg = {};
16032e1dea40SMichal Kazior 	struct survey_info *survey;
16042e1dea40SMichal Kazior 	u32 err_code, freq, cmd_flags, noise_floor, rx_clear_count, cycle_count;
160532653cf1SMichal Kazior 	int idx, ret;
16062e1dea40SMichal Kazior 
1607d7579d12SMichal Kazior 	ret = ath10k_wmi_pull_ch_info(ar, skb, &arg);
160832653cf1SMichal Kazior 	if (ret) {
160932653cf1SMichal Kazior 		ath10k_warn(ar, "failed to parse chan info event: %d\n", ret);
161032653cf1SMichal Kazior 		return;
161132653cf1SMichal Kazior 	}
16122e1dea40SMichal Kazior 
161332653cf1SMichal Kazior 	err_code = __le32_to_cpu(arg.err_code);
161432653cf1SMichal Kazior 	freq = __le32_to_cpu(arg.freq);
161532653cf1SMichal Kazior 	cmd_flags = __le32_to_cpu(arg.cmd_flags);
161632653cf1SMichal Kazior 	noise_floor = __le32_to_cpu(arg.noise_floor);
161732653cf1SMichal Kazior 	rx_clear_count = __le32_to_cpu(arg.rx_clear_count);
161832653cf1SMichal Kazior 	cycle_count = __le32_to_cpu(arg.cycle_count);
16192e1dea40SMichal Kazior 
16207aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
16212e1dea40SMichal Kazior 		   "chan info err_code %d freq %d cmd_flags %d noise_floor %d rx_clear_count %d cycle_count %d\n",
16222e1dea40SMichal Kazior 		   err_code, freq, cmd_flags, noise_floor, rx_clear_count,
16232e1dea40SMichal Kazior 		   cycle_count);
16242e1dea40SMichal Kazior 
16252e1dea40SMichal Kazior 	spin_lock_bh(&ar->data_lock);
16262e1dea40SMichal Kazior 
16275c81c7fdSMichal Kazior 	switch (ar->scan.state) {
16285c81c7fdSMichal Kazior 	case ATH10K_SCAN_IDLE:
16295c81c7fdSMichal Kazior 	case ATH10K_SCAN_STARTING:
16307aa7a72aSMichal Kazior 		ath10k_warn(ar, "received chan info event without a scan request, ignoring\n");
16312e1dea40SMichal Kazior 		goto exit;
16325c81c7fdSMichal Kazior 	case ATH10K_SCAN_RUNNING:
16335c81c7fdSMichal Kazior 	case ATH10K_SCAN_ABORTING:
16345c81c7fdSMichal Kazior 		break;
16352e1dea40SMichal Kazior 	}
16362e1dea40SMichal Kazior 
16372e1dea40SMichal Kazior 	idx = freq_to_idx(ar, freq);
16382e1dea40SMichal Kazior 	if (idx >= ARRAY_SIZE(ar->survey)) {
16397aa7a72aSMichal Kazior 		ath10k_warn(ar, "chan info: invalid frequency %d (idx %d out of bounds)\n",
16402e1dea40SMichal Kazior 			    freq, idx);
16412e1dea40SMichal Kazior 		goto exit;
16422e1dea40SMichal Kazior 	}
16432e1dea40SMichal Kazior 
16442e1dea40SMichal Kazior 	if (cmd_flags & WMI_CHAN_INFO_FLAG_COMPLETE) {
16452e1dea40SMichal Kazior 		/* During scanning chan info is reported twice for each
16462e1dea40SMichal Kazior 		 * visited channel. The reported cycle count is global
16472e1dea40SMichal Kazior 		 * and per-channel cycle count must be calculated */
16482e1dea40SMichal Kazior 
16492e1dea40SMichal Kazior 		cycle_count -= ar->survey_last_cycle_count;
16502e1dea40SMichal Kazior 		rx_clear_count -= ar->survey_last_rx_clear_count;
16512e1dea40SMichal Kazior 
16522e1dea40SMichal Kazior 		survey = &ar->survey[idx];
16532e1dea40SMichal Kazior 		survey->channel_time = WMI_CHAN_INFO_MSEC(cycle_count);
16542e1dea40SMichal Kazior 		survey->channel_time_rx = WMI_CHAN_INFO_MSEC(rx_clear_count);
16552e1dea40SMichal Kazior 		survey->noise = noise_floor;
16562e1dea40SMichal Kazior 		survey->filled = SURVEY_INFO_CHANNEL_TIME |
16572e1dea40SMichal Kazior 				 SURVEY_INFO_CHANNEL_TIME_RX |
16582e1dea40SMichal Kazior 				 SURVEY_INFO_NOISE_DBM;
16592e1dea40SMichal Kazior 	}
16602e1dea40SMichal Kazior 
16612e1dea40SMichal Kazior 	ar->survey_last_rx_clear_count = rx_clear_count;
16622e1dea40SMichal Kazior 	ar->survey_last_cycle_count = cycle_count;
16632e1dea40SMichal Kazior 
16642e1dea40SMichal Kazior exit:
16652e1dea40SMichal Kazior 	spin_unlock_bh(&ar->data_lock);
16665e3dd157SKalle Valo }
16675e3dd157SKalle Valo 
16680226d602SMichal Kazior void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb)
16695e3dd157SKalle Valo {
16707aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_ECHO_EVENTID\n");
16715e3dd157SKalle Valo }
16725e3dd157SKalle Valo 
16730226d602SMichal Kazior int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb)
16745e3dd157SKalle Valo {
16757aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event debug mesg len %d\n",
1676869526b9SKalle Valo 		   skb->len);
1677869526b9SKalle Valo 
1678d35a6c18SMichal Kazior 	trace_ath10k_wmi_dbglog(ar, skb->data, skb->len);
1679869526b9SKalle Valo 
1680869526b9SKalle Valo 	return 0;
16815e3dd157SKalle Valo }
16825e3dd157SKalle Valo 
16830226d602SMichal Kazior void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src,
16845326849aSMichal Kazior 				struct ath10k_fw_stats_pdev *dst)
1685d15fb520SMichal Kazior {
1686d15fb520SMichal Kazior 	const struct wal_dbg_tx_stats *tx = &src->wal.tx;
1687d15fb520SMichal Kazior 	const struct wal_dbg_rx_stats *rx = &src->wal.rx;
1688d15fb520SMichal Kazior 
1689d15fb520SMichal Kazior 	dst->ch_noise_floor = __le32_to_cpu(src->chan_nf);
1690d15fb520SMichal Kazior 	dst->tx_frame_count = __le32_to_cpu(src->tx_frame_count);
1691d15fb520SMichal Kazior 	dst->rx_frame_count = __le32_to_cpu(src->rx_frame_count);
1692d15fb520SMichal Kazior 	dst->rx_clear_count = __le32_to_cpu(src->rx_clear_count);
1693d15fb520SMichal Kazior 	dst->cycle_count = __le32_to_cpu(src->cycle_count);
1694d15fb520SMichal Kazior 	dst->phy_err_count = __le32_to_cpu(src->phy_err_count);
1695d15fb520SMichal Kazior 	dst->chan_tx_power = __le32_to_cpu(src->chan_tx_pwr);
1696d15fb520SMichal Kazior 
1697d15fb520SMichal Kazior 	dst->comp_queued = __le32_to_cpu(tx->comp_queued);
1698d15fb520SMichal Kazior 	dst->comp_delivered = __le32_to_cpu(tx->comp_delivered);
1699d15fb520SMichal Kazior 	dst->msdu_enqued = __le32_to_cpu(tx->msdu_enqued);
1700d15fb520SMichal Kazior 	dst->mpdu_enqued = __le32_to_cpu(tx->mpdu_enqued);
1701d15fb520SMichal Kazior 	dst->wmm_drop = __le32_to_cpu(tx->wmm_drop);
1702d15fb520SMichal Kazior 	dst->local_enqued = __le32_to_cpu(tx->local_enqued);
1703d15fb520SMichal Kazior 	dst->local_freed = __le32_to_cpu(tx->local_freed);
1704d15fb520SMichal Kazior 	dst->hw_queued = __le32_to_cpu(tx->hw_queued);
1705d15fb520SMichal Kazior 	dst->hw_reaped = __le32_to_cpu(tx->hw_reaped);
1706d15fb520SMichal Kazior 	dst->underrun = __le32_to_cpu(tx->underrun);
1707d15fb520SMichal Kazior 	dst->tx_abort = __le32_to_cpu(tx->tx_abort);
1708d15fb520SMichal Kazior 	dst->mpdus_requed = __le32_to_cpu(tx->mpdus_requed);
1709d15fb520SMichal Kazior 	dst->tx_ko = __le32_to_cpu(tx->tx_ko);
1710d15fb520SMichal Kazior 	dst->data_rc = __le32_to_cpu(tx->data_rc);
1711d15fb520SMichal Kazior 	dst->self_triggers = __le32_to_cpu(tx->self_triggers);
1712d15fb520SMichal Kazior 	dst->sw_retry_failure = __le32_to_cpu(tx->sw_retry_failure);
1713d15fb520SMichal Kazior 	dst->illgl_rate_phy_err = __le32_to_cpu(tx->illgl_rate_phy_err);
1714d15fb520SMichal Kazior 	dst->pdev_cont_xretry = __le32_to_cpu(tx->pdev_cont_xretry);
1715d15fb520SMichal Kazior 	dst->pdev_tx_timeout = __le32_to_cpu(tx->pdev_tx_timeout);
1716d15fb520SMichal Kazior 	dst->pdev_resets = __le32_to_cpu(tx->pdev_resets);
1717d15fb520SMichal Kazior 	dst->phy_underrun = __le32_to_cpu(tx->phy_underrun);
1718d15fb520SMichal Kazior 	dst->txop_ovf = __le32_to_cpu(tx->txop_ovf);
1719d15fb520SMichal Kazior 
1720d15fb520SMichal Kazior 	dst->mid_ppdu_route_change = __le32_to_cpu(rx->mid_ppdu_route_change);
1721d15fb520SMichal Kazior 	dst->status_rcvd = __le32_to_cpu(rx->status_rcvd);
1722d15fb520SMichal Kazior 	dst->r0_frags = __le32_to_cpu(rx->r0_frags);
1723d15fb520SMichal Kazior 	dst->r1_frags = __le32_to_cpu(rx->r1_frags);
1724d15fb520SMichal Kazior 	dst->r2_frags = __le32_to_cpu(rx->r2_frags);
1725d15fb520SMichal Kazior 	dst->r3_frags = __le32_to_cpu(rx->r3_frags);
1726d15fb520SMichal Kazior 	dst->htt_msdus = __le32_to_cpu(rx->htt_msdus);
1727d15fb520SMichal Kazior 	dst->htt_mpdus = __le32_to_cpu(rx->htt_mpdus);
1728d15fb520SMichal Kazior 	dst->loc_msdus = __le32_to_cpu(rx->loc_msdus);
1729d15fb520SMichal Kazior 	dst->loc_mpdus = __le32_to_cpu(rx->loc_mpdus);
1730d15fb520SMichal Kazior 	dst->oversize_amsdu = __le32_to_cpu(rx->oversize_amsdu);
1731d15fb520SMichal Kazior 	dst->phy_errs = __le32_to_cpu(rx->phy_errs);
1732d15fb520SMichal Kazior 	dst->phy_err_drop = __le32_to_cpu(rx->phy_err_drop);
1733d15fb520SMichal Kazior 	dst->mpdu_errs = __le32_to_cpu(rx->mpdu_errs);
1734d15fb520SMichal Kazior }
1735d15fb520SMichal Kazior 
17360226d602SMichal Kazior void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src,
173760ef401aSMichal Kazior 				struct ath10k_fw_stats_peer *dst)
1738d15fb520SMichal Kazior {
1739d15fb520SMichal Kazior 	ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
1740d15fb520SMichal Kazior 	dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
1741d15fb520SMichal Kazior 	dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
1742d15fb520SMichal Kazior }
1743d15fb520SMichal Kazior 
1744d7579d12SMichal Kazior static int ath10k_wmi_main_op_pull_fw_stats(struct ath10k *ar,
1745d15fb520SMichal Kazior 					    struct sk_buff *skb,
174660ef401aSMichal Kazior 					    struct ath10k_fw_stats *stats)
1747d15fb520SMichal Kazior {
1748d15fb520SMichal Kazior 	const struct wmi_stats_event *ev = (void *)skb->data;
1749d15fb520SMichal Kazior 	u32 num_pdev_stats, num_vdev_stats, num_peer_stats;
1750d15fb520SMichal Kazior 	int i;
1751d15fb520SMichal Kazior 
1752d15fb520SMichal Kazior 	if (!skb_pull(skb, sizeof(*ev)))
1753d15fb520SMichal Kazior 		return -EPROTO;
1754d15fb520SMichal Kazior 
1755d15fb520SMichal Kazior 	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
1756d15fb520SMichal Kazior 	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
1757d15fb520SMichal Kazior 	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
1758d15fb520SMichal Kazior 
17595326849aSMichal Kazior 	for (i = 0; i < num_pdev_stats; i++) {
1760d15fb520SMichal Kazior 		const struct wmi_pdev_stats *src;
17615326849aSMichal Kazior 		struct ath10k_fw_stats_pdev *dst;
1762d15fb520SMichal Kazior 
1763d15fb520SMichal Kazior 		src = (void *)skb->data;
1764d15fb520SMichal Kazior 		if (!skb_pull(skb, sizeof(*src)))
1765d15fb520SMichal Kazior 			return -EPROTO;
1766d15fb520SMichal Kazior 
17675326849aSMichal Kazior 		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
17685326849aSMichal Kazior 		if (!dst)
17695326849aSMichal Kazior 			continue;
17705326849aSMichal Kazior 
17715326849aSMichal Kazior 		ath10k_wmi_pull_pdev_stats(src, dst);
17725326849aSMichal Kazior 		list_add_tail(&dst->list, &stats->pdevs);
1773d15fb520SMichal Kazior 	}
1774d15fb520SMichal Kazior 
1775d15fb520SMichal Kazior 	/* fw doesn't implement vdev stats */
1776d15fb520SMichal Kazior 
1777d15fb520SMichal Kazior 	for (i = 0; i < num_peer_stats; i++) {
1778d15fb520SMichal Kazior 		const struct wmi_peer_stats *src;
17795326849aSMichal Kazior 		struct ath10k_fw_stats_peer *dst;
1780d15fb520SMichal Kazior 
1781d15fb520SMichal Kazior 		src = (void *)skb->data;
1782d15fb520SMichal Kazior 		if (!skb_pull(skb, sizeof(*src)))
1783d15fb520SMichal Kazior 			return -EPROTO;
1784d15fb520SMichal Kazior 
17855326849aSMichal Kazior 		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
17865326849aSMichal Kazior 		if (!dst)
17875326849aSMichal Kazior 			continue;
17885326849aSMichal Kazior 
17895326849aSMichal Kazior 		ath10k_wmi_pull_peer_stats(src, dst);
17905326849aSMichal Kazior 		list_add_tail(&dst->list, &stats->peers);
1791d15fb520SMichal Kazior 	}
1792d15fb520SMichal Kazior 
1793d15fb520SMichal Kazior 	return 0;
1794d15fb520SMichal Kazior }
1795d15fb520SMichal Kazior 
1796d7579d12SMichal Kazior static int ath10k_wmi_10x_op_pull_fw_stats(struct ath10k *ar,
1797d15fb520SMichal Kazior 					   struct sk_buff *skb,
179860ef401aSMichal Kazior 					   struct ath10k_fw_stats *stats)
1799d15fb520SMichal Kazior {
1800d15fb520SMichal Kazior 	const struct wmi_stats_event *ev = (void *)skb->data;
1801d15fb520SMichal Kazior 	u32 num_pdev_stats, num_vdev_stats, num_peer_stats;
1802d15fb520SMichal Kazior 	int i;
1803d15fb520SMichal Kazior 
1804d15fb520SMichal Kazior 	if (!skb_pull(skb, sizeof(*ev)))
1805d15fb520SMichal Kazior 		return -EPROTO;
1806d15fb520SMichal Kazior 
1807d15fb520SMichal Kazior 	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
1808d15fb520SMichal Kazior 	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
1809d15fb520SMichal Kazior 	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
1810d15fb520SMichal Kazior 
18115326849aSMichal Kazior 	for (i = 0; i < num_pdev_stats; i++) {
1812d15fb520SMichal Kazior 		const struct wmi_10x_pdev_stats *src;
18135326849aSMichal Kazior 		struct ath10k_fw_stats_pdev *dst;
1814d15fb520SMichal Kazior 
1815d15fb520SMichal Kazior 		src = (void *)skb->data;
1816d15fb520SMichal Kazior 		if (!skb_pull(skb, sizeof(*src)))
1817d15fb520SMichal Kazior 			return -EPROTO;
1818d15fb520SMichal Kazior 
18195326849aSMichal Kazior 		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
18205326849aSMichal Kazior 		if (!dst)
18215326849aSMichal Kazior 			continue;
1822d15fb520SMichal Kazior 
18235326849aSMichal Kazior 		ath10k_wmi_pull_pdev_stats(&src->old, dst);
18245326849aSMichal Kazior 
18255326849aSMichal Kazior 		dst->ack_rx_bad = __le32_to_cpu(src->ack_rx_bad);
18265326849aSMichal Kazior 		dst->rts_bad = __le32_to_cpu(src->rts_bad);
18275326849aSMichal Kazior 		dst->rts_good = __le32_to_cpu(src->rts_good);
18285326849aSMichal Kazior 		dst->fcs_bad = __le32_to_cpu(src->fcs_bad);
18295326849aSMichal Kazior 		dst->no_beacons = __le32_to_cpu(src->no_beacons);
18305326849aSMichal Kazior 		dst->mib_int_count = __le32_to_cpu(src->mib_int_count);
18315326849aSMichal Kazior 
18325326849aSMichal Kazior 		list_add_tail(&dst->list, &stats->pdevs);
1833d15fb520SMichal Kazior 	}
1834d15fb520SMichal Kazior 
1835d15fb520SMichal Kazior 	/* fw doesn't implement vdev stats */
1836d15fb520SMichal Kazior 
1837d15fb520SMichal Kazior 	for (i = 0; i < num_peer_stats; i++) {
1838d15fb520SMichal Kazior 		const struct wmi_10x_peer_stats *src;
18395326849aSMichal Kazior 		struct ath10k_fw_stats_peer *dst;
1840d15fb520SMichal Kazior 
1841d15fb520SMichal Kazior 		src = (void *)skb->data;
1842d15fb520SMichal Kazior 		if (!skb_pull(skb, sizeof(*src)))
1843d15fb520SMichal Kazior 			return -EPROTO;
1844d15fb520SMichal Kazior 
18455326849aSMichal Kazior 		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
18465326849aSMichal Kazior 		if (!dst)
18475326849aSMichal Kazior 			continue;
1848d15fb520SMichal Kazior 
18495326849aSMichal Kazior 		ath10k_wmi_pull_peer_stats(&src->old, dst);
18505326849aSMichal Kazior 
18515326849aSMichal Kazior 		dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
18525326849aSMichal Kazior 
18535326849aSMichal Kazior 		list_add_tail(&dst->list, &stats->peers);
1854d15fb520SMichal Kazior 	}
1855d15fb520SMichal Kazior 
1856d15fb520SMichal Kazior 	return 0;
1857d15fb520SMichal Kazior }
1858d15fb520SMichal Kazior 
18590226d602SMichal Kazior void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb)
18605e3dd157SKalle Valo {
18617aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n");
186260ef401aSMichal Kazior 	ath10k_debug_fw_stats_process(ar, skb);
18635e3dd157SKalle Valo }
18645e3dd157SKalle Valo 
1865d7579d12SMichal Kazior static int
1866d7579d12SMichal Kazior ath10k_wmi_op_pull_vdev_start_ev(struct ath10k *ar, struct sk_buff *skb,
186732653cf1SMichal Kazior 				 struct wmi_vdev_start_ev_arg *arg)
186832653cf1SMichal Kazior {
186932653cf1SMichal Kazior 	struct wmi_vdev_start_response_event *ev = (void *)skb->data;
187032653cf1SMichal Kazior 
187132653cf1SMichal Kazior 	if (skb->len < sizeof(*ev))
187232653cf1SMichal Kazior 		return -EPROTO;
187332653cf1SMichal Kazior 
187432653cf1SMichal Kazior 	skb_pull(skb, sizeof(*ev));
187532653cf1SMichal Kazior 	arg->vdev_id = ev->vdev_id;
187632653cf1SMichal Kazior 	arg->req_id = ev->req_id;
187732653cf1SMichal Kazior 	arg->resp_type = ev->resp_type;
187832653cf1SMichal Kazior 	arg->status = ev->status;
187932653cf1SMichal Kazior 
188032653cf1SMichal Kazior 	return 0;
188132653cf1SMichal Kazior }
188232653cf1SMichal Kazior 
18830226d602SMichal Kazior void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, struct sk_buff *skb)
18845e3dd157SKalle Valo {
188532653cf1SMichal Kazior 	struct wmi_vdev_start_ev_arg arg = {};
188632653cf1SMichal Kazior 	int ret;
18875e3dd157SKalle Valo 
18887aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_START_RESP_EVENTID\n");
18895e3dd157SKalle Valo 
1890d7579d12SMichal Kazior 	ret = ath10k_wmi_pull_vdev_start(ar, skb, &arg);
189132653cf1SMichal Kazior 	if (ret) {
189232653cf1SMichal Kazior 		ath10k_warn(ar, "failed to parse vdev start event: %d\n", ret);
189332653cf1SMichal Kazior 		return;
189432653cf1SMichal Kazior 	}
18955e3dd157SKalle Valo 
189632653cf1SMichal Kazior 	if (WARN_ON(__le32_to_cpu(arg.status)))
18975e3dd157SKalle Valo 		return;
18985e3dd157SKalle Valo 
18995e3dd157SKalle Valo 	complete(&ar->vdev_setup_done);
19005e3dd157SKalle Valo }
19015e3dd157SKalle Valo 
19020226d602SMichal Kazior void ath10k_wmi_event_vdev_stopped(struct ath10k *ar, struct sk_buff *skb)
19035e3dd157SKalle Valo {
19047aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_STOPPED_EVENTID\n");
19055e3dd157SKalle Valo 	complete(&ar->vdev_setup_done);
19065e3dd157SKalle Valo }
19075e3dd157SKalle Valo 
1908d7579d12SMichal Kazior static int
1909d7579d12SMichal Kazior ath10k_wmi_op_pull_peer_kick_ev(struct ath10k *ar, struct sk_buff *skb,
191032653cf1SMichal Kazior 				struct wmi_peer_kick_ev_arg *arg)
191132653cf1SMichal Kazior {
191232653cf1SMichal Kazior 	struct wmi_peer_sta_kickout_event *ev = (void *)skb->data;
191332653cf1SMichal Kazior 
191432653cf1SMichal Kazior 	if (skb->len < sizeof(*ev))
191532653cf1SMichal Kazior 		return -EPROTO;
191632653cf1SMichal Kazior 
191732653cf1SMichal Kazior 	skb_pull(skb, sizeof(*ev));
191832653cf1SMichal Kazior 	arg->mac_addr = ev->peer_macaddr.addr;
191932653cf1SMichal Kazior 
192032653cf1SMichal Kazior 	return 0;
192132653cf1SMichal Kazior }
192232653cf1SMichal Kazior 
19230226d602SMichal Kazior void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar, struct sk_buff *skb)
19245e3dd157SKalle Valo {
192532653cf1SMichal Kazior 	struct wmi_peer_kick_ev_arg arg = {};
19265a13e76eSKalle Valo 	struct ieee80211_sta *sta;
192732653cf1SMichal Kazior 	int ret;
19285a13e76eSKalle Valo 
1929d7579d12SMichal Kazior 	ret = ath10k_wmi_pull_peer_kick(ar, skb, &arg);
193032653cf1SMichal Kazior 	if (ret) {
193132653cf1SMichal Kazior 		ath10k_warn(ar, "failed to parse peer kickout event: %d\n",
193232653cf1SMichal Kazior 			    ret);
193332653cf1SMichal Kazior 		return;
193432653cf1SMichal Kazior 	}
19355a13e76eSKalle Valo 
19367aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event peer sta kickout %pM\n",
193732653cf1SMichal Kazior 		   arg.mac_addr);
19385a13e76eSKalle Valo 
19395a13e76eSKalle Valo 	rcu_read_lock();
19405a13e76eSKalle Valo 
194132653cf1SMichal Kazior 	sta = ieee80211_find_sta_by_ifaddr(ar->hw, arg.mac_addr, NULL);
19425a13e76eSKalle Valo 	if (!sta) {
19437aa7a72aSMichal Kazior 		ath10k_warn(ar, "Spurious quick kickout for STA %pM\n",
194432653cf1SMichal Kazior 			    arg.mac_addr);
19455a13e76eSKalle Valo 		goto exit;
19465a13e76eSKalle Valo 	}
19475a13e76eSKalle Valo 
19485a13e76eSKalle Valo 	ieee80211_report_low_ack(sta, 10);
19495a13e76eSKalle Valo 
19505a13e76eSKalle Valo exit:
19515a13e76eSKalle Valo 	rcu_read_unlock();
19525e3dd157SKalle Valo }
19535e3dd157SKalle Valo 
19545e3dd157SKalle Valo /*
19555e3dd157SKalle Valo  * FIXME
19565e3dd157SKalle Valo  *
19575e3dd157SKalle Valo  * We don't report to mac80211 sleep state of connected
19585e3dd157SKalle Valo  * stations. Due to this mac80211 can't fill in TIM IE
19595e3dd157SKalle Valo  * correctly.
19605e3dd157SKalle Valo  *
19615e3dd157SKalle Valo  * I know of no way of getting nullfunc frames that contain
19625e3dd157SKalle Valo  * sleep transition from connected stations - these do not
19635e3dd157SKalle Valo  * seem to be sent from the target to the host. There also
19645e3dd157SKalle Valo  * doesn't seem to be a dedicated event for that. So the
19655e3dd157SKalle Valo  * only way left to do this would be to read tim_bitmap
19665e3dd157SKalle Valo  * during SWBA.
19675e3dd157SKalle Valo  *
19685e3dd157SKalle Valo  * We could probably try using tim_bitmap from SWBA to tell
19695e3dd157SKalle Valo  * mac80211 which stations are asleep and which are not. The
19705e3dd157SKalle Valo  * problem here is calling mac80211 functions so many times
19715e3dd157SKalle Valo  * could take too long and make us miss the time to submit
19725e3dd157SKalle Valo  * the beacon to the target.
19735e3dd157SKalle Valo  *
19745e3dd157SKalle Valo  * So as a workaround we try to extend the TIM IE if there
19755e3dd157SKalle Valo  * is unicast buffered for stations with aid > 7 and fill it
19765e3dd157SKalle Valo  * in ourselves.
19775e3dd157SKalle Valo  */
19785e3dd157SKalle Valo static void ath10k_wmi_update_tim(struct ath10k *ar,
19795e3dd157SKalle Valo 				  struct ath10k_vif *arvif,
19805e3dd157SKalle Valo 				  struct sk_buff *bcn,
198132653cf1SMichal Kazior 				  const struct wmi_tim_info *tim_info)
19825e3dd157SKalle Valo {
19835e3dd157SKalle Valo 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)bcn->data;
19845e3dd157SKalle Valo 	struct ieee80211_tim_ie *tim;
19855e3dd157SKalle Valo 	u8 *ies, *ie;
19865e3dd157SKalle Valo 	u8 ie_len, pvm_len;
1987af762c0bSKalle Valo 	__le32 t;
1988af762c0bSKalle Valo 	u32 v;
19895e3dd157SKalle Valo 
19905e3dd157SKalle Valo 	/* if next SWBA has no tim_changed the tim_bitmap is garbage.
19915e3dd157SKalle Valo 	 * we must copy the bitmap upon change and reuse it later */
199232653cf1SMichal Kazior 	if (__le32_to_cpu(tim_info->tim_changed)) {
19935e3dd157SKalle Valo 		int i;
19945e3dd157SKalle Valo 
19955e3dd157SKalle Valo 		BUILD_BUG_ON(sizeof(arvif->u.ap.tim_bitmap) !=
199632653cf1SMichal Kazior 			     sizeof(tim_info->tim_bitmap));
19975e3dd157SKalle Valo 
19985e3dd157SKalle Valo 		for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++) {
199932653cf1SMichal Kazior 			t = tim_info->tim_bitmap[i / 4];
2000af762c0bSKalle Valo 			v = __le32_to_cpu(t);
20015e3dd157SKalle Valo 			arvif->u.ap.tim_bitmap[i] = (v >> ((i % 4) * 8)) & 0xFF;
20025e3dd157SKalle Valo 		}
20035e3dd157SKalle Valo 
20045e3dd157SKalle Valo 		/* FW reports either length 0 or 16
20055e3dd157SKalle Valo 		 * so we calculate this on our own */
20065e3dd157SKalle Valo 		arvif->u.ap.tim_len = 0;
20075e3dd157SKalle Valo 		for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++)
20085e3dd157SKalle Valo 			if (arvif->u.ap.tim_bitmap[i])
20095e3dd157SKalle Valo 				arvif->u.ap.tim_len = i;
20105e3dd157SKalle Valo 
20115e3dd157SKalle Valo 		arvif->u.ap.tim_len++;
20125e3dd157SKalle Valo 	}
20135e3dd157SKalle Valo 
20145e3dd157SKalle Valo 	ies = bcn->data;
20155e3dd157SKalle Valo 	ies += ieee80211_hdrlen(hdr->frame_control);
20165e3dd157SKalle Valo 	ies += 12; /* fixed parameters */
20175e3dd157SKalle Valo 
20185e3dd157SKalle Valo 	ie = (u8 *)cfg80211_find_ie(WLAN_EID_TIM, ies,
20195e3dd157SKalle Valo 				    (u8 *)skb_tail_pointer(bcn) - ies);
20205e3dd157SKalle Valo 	if (!ie) {
202109af8f85SMichal Kazior 		if (arvif->vdev_type != WMI_VDEV_TYPE_IBSS)
20227aa7a72aSMichal Kazior 			ath10k_warn(ar, "no tim ie found;\n");
20235e3dd157SKalle Valo 		return;
20245e3dd157SKalle Valo 	}
20255e3dd157SKalle Valo 
20265e3dd157SKalle Valo 	tim = (void *)ie + 2;
20275e3dd157SKalle Valo 	ie_len = ie[1];
20285e3dd157SKalle Valo 	pvm_len = ie_len - 3; /* exclude dtim count, dtim period, bmap ctl */
20295e3dd157SKalle Valo 
20305e3dd157SKalle Valo 	if (pvm_len < arvif->u.ap.tim_len) {
20315e3dd157SKalle Valo 		int expand_size = sizeof(arvif->u.ap.tim_bitmap) - pvm_len;
20325e3dd157SKalle Valo 		int move_size = skb_tail_pointer(bcn) - (ie + 2 + ie_len);
20335e3dd157SKalle Valo 		void *next_ie = ie + 2 + ie_len;
20345e3dd157SKalle Valo 
20355e3dd157SKalle Valo 		if (skb_put(bcn, expand_size)) {
20365e3dd157SKalle Valo 			memmove(next_ie + expand_size, next_ie, move_size);
20375e3dd157SKalle Valo 
20385e3dd157SKalle Valo 			ie[1] += expand_size;
20395e3dd157SKalle Valo 			ie_len += expand_size;
20405e3dd157SKalle Valo 			pvm_len += expand_size;
20415e3dd157SKalle Valo 		} else {
20427aa7a72aSMichal Kazior 			ath10k_warn(ar, "tim expansion failed\n");
20435e3dd157SKalle Valo 		}
20445e3dd157SKalle Valo 	}
20455e3dd157SKalle Valo 
20465e3dd157SKalle Valo 	if (pvm_len > sizeof(arvif->u.ap.tim_bitmap)) {
20477aa7a72aSMichal Kazior 		ath10k_warn(ar, "tim pvm length is too great (%d)\n", pvm_len);
20485e3dd157SKalle Valo 		return;
20495e3dd157SKalle Valo 	}
20505e3dd157SKalle Valo 
205132653cf1SMichal Kazior 	tim->bitmap_ctrl = !!__le32_to_cpu(tim_info->tim_mcast);
20525e3dd157SKalle Valo 	memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len);
20535e3dd157SKalle Valo 
2054748afc47SMichal Kazior 	if (tim->dtim_count == 0) {
2055748afc47SMichal Kazior 		ATH10K_SKB_CB(bcn)->bcn.dtim_zero = true;
2056748afc47SMichal Kazior 
205732653cf1SMichal Kazior 		if (__le32_to_cpu(tim_info->tim_mcast) == 1)
2058748afc47SMichal Kazior 			ATH10K_SKB_CB(bcn)->bcn.deliver_cab = true;
2059748afc47SMichal Kazior 	}
2060748afc47SMichal Kazior 
20617aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n",
20625e3dd157SKalle Valo 		   tim->dtim_count, tim->dtim_period,
20635e3dd157SKalle Valo 		   tim->bitmap_ctrl, pvm_len);
20645e3dd157SKalle Valo }
20655e3dd157SKalle Valo 
20665e3dd157SKalle Valo static void ath10k_p2p_fill_noa_ie(u8 *data, u32 len,
206732653cf1SMichal Kazior 				   const struct wmi_p2p_noa_info *noa)
20685e3dd157SKalle Valo {
20695e3dd157SKalle Valo 	struct ieee80211_p2p_noa_attr *noa_attr;
20705e3dd157SKalle Valo 	u8  ctwindow_oppps = noa->ctwindow_oppps;
20715e3dd157SKalle Valo 	u8 ctwindow = ctwindow_oppps >> WMI_P2P_OPPPS_CTWINDOW_OFFSET;
20725e3dd157SKalle Valo 	bool oppps = !!(ctwindow_oppps & WMI_P2P_OPPPS_ENABLE_BIT);
20735e3dd157SKalle Valo 	__le16 *noa_attr_len;
20745e3dd157SKalle Valo 	u16 attr_len;
20755e3dd157SKalle Valo 	u8 noa_descriptors = noa->num_descriptors;
20765e3dd157SKalle Valo 	int i;
20775e3dd157SKalle Valo 
20785e3dd157SKalle Valo 	/* P2P IE */
20795e3dd157SKalle Valo 	data[0] = WLAN_EID_VENDOR_SPECIFIC;
20805e3dd157SKalle Valo 	data[1] = len - 2;
20815e3dd157SKalle Valo 	data[2] = (WLAN_OUI_WFA >> 16) & 0xff;
20825e3dd157SKalle Valo 	data[3] = (WLAN_OUI_WFA >> 8) & 0xff;
20835e3dd157SKalle Valo 	data[4] = (WLAN_OUI_WFA >> 0) & 0xff;
20845e3dd157SKalle Valo 	data[5] = WLAN_OUI_TYPE_WFA_P2P;
20855e3dd157SKalle Valo 
20865e3dd157SKalle Valo 	/* NOA ATTR */
20875e3dd157SKalle Valo 	data[6] = IEEE80211_P2P_ATTR_ABSENCE_NOTICE;
20885e3dd157SKalle Valo 	noa_attr_len = (__le16 *)&data[7]; /* 2 bytes */
20895e3dd157SKalle Valo 	noa_attr = (struct ieee80211_p2p_noa_attr *)&data[9];
20905e3dd157SKalle Valo 
20915e3dd157SKalle Valo 	noa_attr->index = noa->index;
20925e3dd157SKalle Valo 	noa_attr->oppps_ctwindow = ctwindow;
20935e3dd157SKalle Valo 	if (oppps)
20945e3dd157SKalle Valo 		noa_attr->oppps_ctwindow |= IEEE80211_P2P_OPPPS_ENABLE_BIT;
20955e3dd157SKalle Valo 
20965e3dd157SKalle Valo 	for (i = 0; i < noa_descriptors; i++) {
20975e3dd157SKalle Valo 		noa_attr->desc[i].count =
20985e3dd157SKalle Valo 			__le32_to_cpu(noa->descriptors[i].type_count);
20995e3dd157SKalle Valo 		noa_attr->desc[i].duration = noa->descriptors[i].duration;
21005e3dd157SKalle Valo 		noa_attr->desc[i].interval = noa->descriptors[i].interval;
21015e3dd157SKalle Valo 		noa_attr->desc[i].start_time = noa->descriptors[i].start_time;
21025e3dd157SKalle Valo 	}
21035e3dd157SKalle Valo 
21045e3dd157SKalle Valo 	attr_len = 2; /* index + oppps_ctwindow */
21055e3dd157SKalle Valo 	attr_len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc);
21065e3dd157SKalle Valo 	*noa_attr_len = __cpu_to_le16(attr_len);
21075e3dd157SKalle Valo }
21085e3dd157SKalle Valo 
210932653cf1SMichal Kazior static u32 ath10k_p2p_calc_noa_ie_len(const struct wmi_p2p_noa_info *noa)
21105e3dd157SKalle Valo {
21115e3dd157SKalle Valo 	u32 len = 0;
21125e3dd157SKalle Valo 	u8 noa_descriptors = noa->num_descriptors;
21135e3dd157SKalle Valo 	u8 opp_ps_info = noa->ctwindow_oppps;
21145e3dd157SKalle Valo 	bool opps_enabled = !!(opp_ps_info & WMI_P2P_OPPPS_ENABLE_BIT);
21155e3dd157SKalle Valo 
21165e3dd157SKalle Valo 	if (!noa_descriptors && !opps_enabled)
21175e3dd157SKalle Valo 		return len;
21185e3dd157SKalle Valo 
21195e3dd157SKalle Valo 	len += 1 + 1 + 4; /* EID + len + OUI */
21205e3dd157SKalle Valo 	len += 1 + 2; /* noa attr  + attr len */
21215e3dd157SKalle Valo 	len += 1 + 1; /* index + oppps_ctwindow */
21225e3dd157SKalle Valo 	len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc);
21235e3dd157SKalle Valo 
21245e3dd157SKalle Valo 	return len;
21255e3dd157SKalle Valo }
21265e3dd157SKalle Valo 
21275e3dd157SKalle Valo static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif,
21285e3dd157SKalle Valo 				  struct sk_buff *bcn,
212932653cf1SMichal Kazior 				  const struct wmi_p2p_noa_info *noa)
21305e3dd157SKalle Valo {
21315e3dd157SKalle Valo 	u8 *new_data, *old_data = arvif->u.ap.noa_data;
21325e3dd157SKalle Valo 	u32 new_len;
21335e3dd157SKalle Valo 
21345e3dd157SKalle Valo 	if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO)
21355e3dd157SKalle Valo 		return;
21365e3dd157SKalle Valo 
21377aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_MGMT, "noa changed: %d\n", noa->changed);
21385e3dd157SKalle Valo 	if (noa->changed & WMI_P2P_NOA_CHANGED_BIT) {
21395e3dd157SKalle Valo 		new_len = ath10k_p2p_calc_noa_ie_len(noa);
21405e3dd157SKalle Valo 		if (!new_len)
21415e3dd157SKalle Valo 			goto cleanup;
21425e3dd157SKalle Valo 
21435e3dd157SKalle Valo 		new_data = kmalloc(new_len, GFP_ATOMIC);
21445e3dd157SKalle Valo 		if (!new_data)
21455e3dd157SKalle Valo 			goto cleanup;
21465e3dd157SKalle Valo 
21475e3dd157SKalle Valo 		ath10k_p2p_fill_noa_ie(new_data, new_len, noa);
21485e3dd157SKalle Valo 
21495e3dd157SKalle Valo 		spin_lock_bh(&ar->data_lock);
21505e3dd157SKalle Valo 		arvif->u.ap.noa_data = new_data;
21515e3dd157SKalle Valo 		arvif->u.ap.noa_len = new_len;
21525e3dd157SKalle Valo 		spin_unlock_bh(&ar->data_lock);
21535e3dd157SKalle Valo 		kfree(old_data);
21545e3dd157SKalle Valo 	}
21555e3dd157SKalle Valo 
21565e3dd157SKalle Valo 	if (arvif->u.ap.noa_data)
21575e3dd157SKalle Valo 		if (!pskb_expand_head(bcn, 0, arvif->u.ap.noa_len, GFP_ATOMIC))
21585e3dd157SKalle Valo 			memcpy(skb_put(bcn, arvif->u.ap.noa_len),
21595e3dd157SKalle Valo 			       arvif->u.ap.noa_data,
21605e3dd157SKalle Valo 			       arvif->u.ap.noa_len);
21615e3dd157SKalle Valo 	return;
21625e3dd157SKalle Valo 
21635e3dd157SKalle Valo cleanup:
21645e3dd157SKalle Valo 	spin_lock_bh(&ar->data_lock);
21655e3dd157SKalle Valo 	arvif->u.ap.noa_data = NULL;
21665e3dd157SKalle Valo 	arvif->u.ap.noa_len = 0;
21675e3dd157SKalle Valo 	spin_unlock_bh(&ar->data_lock);
21685e3dd157SKalle Valo 	kfree(old_data);
21695e3dd157SKalle Valo }
21705e3dd157SKalle Valo 
2171d7579d12SMichal Kazior static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb,
217232653cf1SMichal Kazior 				      struct wmi_swba_ev_arg *arg)
217332653cf1SMichal Kazior {
217432653cf1SMichal Kazior 	struct wmi_host_swba_event *ev = (void *)skb->data;
217532653cf1SMichal Kazior 	u32 map;
217632653cf1SMichal Kazior 	size_t i;
217732653cf1SMichal Kazior 
217832653cf1SMichal Kazior 	if (skb->len < sizeof(*ev))
217932653cf1SMichal Kazior 		return -EPROTO;
218032653cf1SMichal Kazior 
218132653cf1SMichal Kazior 	skb_pull(skb, sizeof(*ev));
218232653cf1SMichal Kazior 	arg->vdev_map = ev->vdev_map;
218332653cf1SMichal Kazior 
218432653cf1SMichal Kazior 	for (i = 0, map = __le32_to_cpu(ev->vdev_map); map; map >>= 1) {
218532653cf1SMichal Kazior 		if (!(map & BIT(0)))
218632653cf1SMichal Kazior 			continue;
218732653cf1SMichal Kazior 
218832653cf1SMichal Kazior 		/* If this happens there were some changes in firmware and
218932653cf1SMichal Kazior 		 * ath10k should update the max size of tim_info array.
219032653cf1SMichal Kazior 		 */
219132653cf1SMichal Kazior 		if (WARN_ON_ONCE(i == ARRAY_SIZE(arg->tim_info)))
219232653cf1SMichal Kazior 			break;
219332653cf1SMichal Kazior 
219432653cf1SMichal Kazior 		arg->tim_info[i] = &ev->bcn_info[i].tim_info;
219532653cf1SMichal Kazior 		arg->noa_info[i] = &ev->bcn_info[i].p2p_noa_info;
219632653cf1SMichal Kazior 		i++;
219732653cf1SMichal Kazior 	}
219832653cf1SMichal Kazior 
219932653cf1SMichal Kazior 	return 0;
220032653cf1SMichal Kazior }
220132653cf1SMichal Kazior 
22020226d602SMichal Kazior void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
22035e3dd157SKalle Valo {
220432653cf1SMichal Kazior 	struct wmi_swba_ev_arg arg = {};
22055e3dd157SKalle Valo 	u32 map;
22065e3dd157SKalle Valo 	int i = -1;
220732653cf1SMichal Kazior 	const struct wmi_tim_info *tim_info;
220832653cf1SMichal Kazior 	const struct wmi_p2p_noa_info *noa_info;
22095e3dd157SKalle Valo 	struct ath10k_vif *arvif;
22105e3dd157SKalle Valo 	struct sk_buff *bcn;
221164badcb6SMichal Kazior 	dma_addr_t paddr;
2212767d34fcSMichal Kazior 	int ret, vdev_id = 0;
22135e3dd157SKalle Valo 
2214d7579d12SMichal Kazior 	ret = ath10k_wmi_pull_swba(ar, skb, &arg);
221532653cf1SMichal Kazior 	if (ret) {
221632653cf1SMichal Kazior 		ath10k_warn(ar, "failed to parse swba event: %d\n", ret);
221732653cf1SMichal Kazior 		return;
221832653cf1SMichal Kazior 	}
221932653cf1SMichal Kazior 
222032653cf1SMichal Kazior 	map = __le32_to_cpu(arg.vdev_map);
22215e3dd157SKalle Valo 
22227aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_MGMT, "mgmt swba vdev_map 0x%x\n",
222332653cf1SMichal Kazior 		   map);
22245e3dd157SKalle Valo 
22255e3dd157SKalle Valo 	for (; map; map >>= 1, vdev_id++) {
22265e3dd157SKalle Valo 		if (!(map & 0x1))
22275e3dd157SKalle Valo 			continue;
22285e3dd157SKalle Valo 
22295e3dd157SKalle Valo 		i++;
22305e3dd157SKalle Valo 
22315e3dd157SKalle Valo 		if (i >= WMI_MAX_AP_VDEV) {
22327aa7a72aSMichal Kazior 			ath10k_warn(ar, "swba has corrupted vdev map\n");
22335e3dd157SKalle Valo 			break;
22345e3dd157SKalle Valo 		}
22355e3dd157SKalle Valo 
223632653cf1SMichal Kazior 		tim_info = arg.tim_info[i];
223732653cf1SMichal Kazior 		noa_info = arg.noa_info[i];
22385e3dd157SKalle Valo 
22397aa7a72aSMichal Kazior 		ath10k_dbg(ar, ATH10K_DBG_MGMT,
22407a8a396bSKalle Valo 			   "mgmt event bcn_info %d tim_len %d mcast %d changed %d num_ps_pending %d bitmap 0x%08x%08x%08x%08x\n",
22415e3dd157SKalle Valo 			   i,
224232653cf1SMichal Kazior 			   __le32_to_cpu(tim_info->tim_len),
224332653cf1SMichal Kazior 			   __le32_to_cpu(tim_info->tim_mcast),
224432653cf1SMichal Kazior 			   __le32_to_cpu(tim_info->tim_changed),
224532653cf1SMichal Kazior 			   __le32_to_cpu(tim_info->tim_num_ps_pending),
224632653cf1SMichal Kazior 			   __le32_to_cpu(tim_info->tim_bitmap[3]),
224732653cf1SMichal Kazior 			   __le32_to_cpu(tim_info->tim_bitmap[2]),
224832653cf1SMichal Kazior 			   __le32_to_cpu(tim_info->tim_bitmap[1]),
224932653cf1SMichal Kazior 			   __le32_to_cpu(tim_info->tim_bitmap[0]));
22505e3dd157SKalle Valo 
22515e3dd157SKalle Valo 		arvif = ath10k_get_arvif(ar, vdev_id);
22525e3dd157SKalle Valo 		if (arvif == NULL) {
22537aa7a72aSMichal Kazior 			ath10k_warn(ar, "no vif for vdev_id %d found\n",
22547aa7a72aSMichal Kazior 				    vdev_id);
22555e3dd157SKalle Valo 			continue;
22565e3dd157SKalle Valo 		}
22575e3dd157SKalle Valo 
2258c2df44b3SMichal Kazior 		/* There are no completions for beacons so wait for next SWBA
2259c2df44b3SMichal Kazior 		 * before telling mac80211 to decrement CSA counter
2260c2df44b3SMichal Kazior 		 *
2261c2df44b3SMichal Kazior 		 * Once CSA counter is completed stop sending beacons until
2262c2df44b3SMichal Kazior 		 * actual channel switch is done */
2263c2df44b3SMichal Kazior 		if (arvif->vif->csa_active &&
2264c2df44b3SMichal Kazior 		    ieee80211_csa_is_complete(arvif->vif)) {
2265c2df44b3SMichal Kazior 			ieee80211_csa_finish(arvif->vif);
2266c2df44b3SMichal Kazior 			continue;
2267c2df44b3SMichal Kazior 		}
2268c2df44b3SMichal Kazior 
22695e3dd157SKalle Valo 		bcn = ieee80211_beacon_get(ar->hw, arvif->vif);
22705e3dd157SKalle Valo 		if (!bcn) {
22717aa7a72aSMichal Kazior 			ath10k_warn(ar, "could not get mac80211 beacon\n");
22725e3dd157SKalle Valo 			continue;
22735e3dd157SKalle Valo 		}
22745e3dd157SKalle Valo 
22754b604558SMichal Kazior 		ath10k_tx_h_seq_no(arvif->vif, bcn);
227632653cf1SMichal Kazior 		ath10k_wmi_update_tim(ar, arvif, bcn, tim_info);
227732653cf1SMichal Kazior 		ath10k_wmi_update_noa(ar, arvif, bcn, noa_info);
22785e3dd157SKalle Valo 
2279ed54388aSMichal Kazior 		spin_lock_bh(&ar->data_lock);
2280748afc47SMichal Kazior 
2281ed54388aSMichal Kazior 		if (arvif->beacon) {
2282748afc47SMichal Kazior 			if (!arvif->beacon_sent)
22837aa7a72aSMichal Kazior 				ath10k_warn(ar, "SWBA overrun on vdev %d\n",
2284ed54388aSMichal Kazior 					    arvif->vdev_id);
2285748afc47SMichal Kazior 
228664badcb6SMichal Kazior 			ath10k_mac_vif_beacon_free(arvif);
2287ed54388aSMichal Kazior 		}
22885e3dd157SKalle Valo 
228964badcb6SMichal Kazior 		if (!arvif->beacon_buf) {
229064badcb6SMichal Kazior 			paddr = dma_map_single(arvif->ar->dev, bcn->data,
229164badcb6SMichal Kazior 					       bcn->len, DMA_TO_DEVICE);
229264badcb6SMichal Kazior 			ret = dma_mapping_error(arvif->ar->dev, paddr);
2293767d34fcSMichal Kazior 			if (ret) {
229464badcb6SMichal Kazior 				ath10k_warn(ar, "failed to map beacon: %d\n",
229564badcb6SMichal Kazior 					    ret);
2296ad3d2153SMichal Kazior 				dev_kfree_skb_any(bcn);
2297767d34fcSMichal Kazior 				goto skip;
2298767d34fcSMichal Kazior 			}
2299748afc47SMichal Kazior 
230064badcb6SMichal Kazior 			ATH10K_SKB_CB(bcn)->paddr = paddr;
230164badcb6SMichal Kazior 		} else {
230264badcb6SMichal Kazior 			if (bcn->len > IEEE80211_MAX_FRAME_LEN) {
230364badcb6SMichal Kazior 				ath10k_warn(ar, "trimming beacon %d -> %d bytes!\n",
230464badcb6SMichal Kazior 					    bcn->len, IEEE80211_MAX_FRAME_LEN);
230564badcb6SMichal Kazior 				skb_trim(bcn, IEEE80211_MAX_FRAME_LEN);
230664badcb6SMichal Kazior 			}
230764badcb6SMichal Kazior 			memcpy(arvif->beacon_buf, bcn->data, bcn->len);
230864badcb6SMichal Kazior 			ATH10K_SKB_CB(bcn)->paddr = arvif->beacon_paddr;
230964badcb6SMichal Kazior 		}
231064badcb6SMichal Kazior 
2311ed54388aSMichal Kazior 		arvif->beacon = bcn;
2312748afc47SMichal Kazior 		arvif->beacon_sent = false;
23135e3dd157SKalle Valo 
23145ce8e7fdSRajkumar Manoharan 		trace_ath10k_tx_hdr(ar, bcn->data, bcn->len);
23155ce8e7fdSRajkumar Manoharan 		trace_ath10k_tx_payload(ar, bcn->data, bcn->len);
23165ce8e7fdSRajkumar Manoharan 
2317ed54388aSMichal Kazior 		ath10k_wmi_tx_beacon_nowait(arvif);
2318767d34fcSMichal Kazior skip:
2319ed54388aSMichal Kazior 		spin_unlock_bh(&ar->data_lock);
23205e3dd157SKalle Valo 	}
23215e3dd157SKalle Valo }
23225e3dd157SKalle Valo 
23230226d602SMichal Kazior void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, struct sk_buff *skb)
23245e3dd157SKalle Valo {
23257aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TBTTOFFSET_UPDATE_EVENTID\n");
23265e3dd157SKalle Valo }
23275e3dd157SKalle Valo 
23289702c686SJanusz Dziedzic static void ath10k_dfs_radar_report(struct ath10k *ar,
23292332d0aeSMichal Kazior 				    const struct wmi_phyerr *phyerr,
23302332d0aeSMichal Kazior 				    const struct phyerr_radar_report *rr,
23319702c686SJanusz Dziedzic 				    u64 tsf)
23329702c686SJanusz Dziedzic {
23339702c686SJanusz Dziedzic 	u32 reg0, reg1, tsf32l;
23349702c686SJanusz Dziedzic 	struct pulse_event pe;
23359702c686SJanusz Dziedzic 	u64 tsf64;
23369702c686SJanusz Dziedzic 	u8 rssi, width;
23379702c686SJanusz Dziedzic 
23389702c686SJanusz Dziedzic 	reg0 = __le32_to_cpu(rr->reg0);
23399702c686SJanusz Dziedzic 	reg1 = __le32_to_cpu(rr->reg1);
23409702c686SJanusz Dziedzic 
23417aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
23429702c686SJanusz Dziedzic 		   "wmi phyerr radar report chirp %d max_width %d agc_total_gain %d pulse_delta_diff %d\n",
23439702c686SJanusz Dziedzic 		   MS(reg0, RADAR_REPORT_REG0_PULSE_IS_CHIRP),
23449702c686SJanusz Dziedzic 		   MS(reg0, RADAR_REPORT_REG0_PULSE_IS_MAX_WIDTH),
23459702c686SJanusz Dziedzic 		   MS(reg0, RADAR_REPORT_REG0_AGC_TOTAL_GAIN),
23469702c686SJanusz Dziedzic 		   MS(reg0, RADAR_REPORT_REG0_PULSE_DELTA_DIFF));
23477aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
23489702c686SJanusz Dziedzic 		   "wmi phyerr radar report pulse_delta_pean %d pulse_sidx %d fft_valid %d agc_mb_gain %d subchan_mask %d\n",
23499702c686SJanusz Dziedzic 		   MS(reg0, RADAR_REPORT_REG0_PULSE_DELTA_PEAK),
23509702c686SJanusz Dziedzic 		   MS(reg0, RADAR_REPORT_REG0_PULSE_SIDX),
23519702c686SJanusz Dziedzic 		   MS(reg1, RADAR_REPORT_REG1_PULSE_SRCH_FFT_VALID),
23529702c686SJanusz Dziedzic 		   MS(reg1, RADAR_REPORT_REG1_PULSE_AGC_MB_GAIN),
23539702c686SJanusz Dziedzic 		   MS(reg1, RADAR_REPORT_REG1_PULSE_SUBCHAN_MASK));
23547aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
23559702c686SJanusz Dziedzic 		   "wmi phyerr radar report pulse_tsf_offset 0x%X pulse_dur: %d\n",
23569702c686SJanusz Dziedzic 		   MS(reg1, RADAR_REPORT_REG1_PULSE_TSF_OFFSET),
23579702c686SJanusz Dziedzic 		   MS(reg1, RADAR_REPORT_REG1_PULSE_DUR));
23589702c686SJanusz Dziedzic 
23599702c686SJanusz Dziedzic 	if (!ar->dfs_detector)
23609702c686SJanusz Dziedzic 		return;
23619702c686SJanusz Dziedzic 
23629702c686SJanusz Dziedzic 	/* report event to DFS pattern detector */
23632332d0aeSMichal Kazior 	tsf32l = __le32_to_cpu(phyerr->tsf_timestamp);
23649702c686SJanusz Dziedzic 	tsf64 = tsf & (~0xFFFFFFFFULL);
23659702c686SJanusz Dziedzic 	tsf64 |= tsf32l;
23669702c686SJanusz Dziedzic 
23679702c686SJanusz Dziedzic 	width = MS(reg1, RADAR_REPORT_REG1_PULSE_DUR);
23682332d0aeSMichal Kazior 	rssi = phyerr->rssi_combined;
23699702c686SJanusz Dziedzic 
23709702c686SJanusz Dziedzic 	/* hardware store this as 8 bit signed value,
23719702c686SJanusz Dziedzic 	 * set to zero if negative number
23729702c686SJanusz Dziedzic 	 */
23739702c686SJanusz Dziedzic 	if (rssi & 0x80)
23749702c686SJanusz Dziedzic 		rssi = 0;
23759702c686SJanusz Dziedzic 
23769702c686SJanusz Dziedzic 	pe.ts = tsf64;
23779702c686SJanusz Dziedzic 	pe.freq = ar->hw->conf.chandef.chan->center_freq;
23789702c686SJanusz Dziedzic 	pe.width = width;
23799702c686SJanusz Dziedzic 	pe.rssi = rssi;
23809702c686SJanusz Dziedzic 
23817aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
23829702c686SJanusz Dziedzic 		   "dfs add pulse freq: %d, width: %d, rssi %d, tsf: %llX\n",
23839702c686SJanusz Dziedzic 		   pe.freq, pe.width, pe.rssi, pe.ts);
23849702c686SJanusz Dziedzic 
23859702c686SJanusz Dziedzic 	ATH10K_DFS_STAT_INC(ar, pulses_detected);
23869702c686SJanusz Dziedzic 
23879702c686SJanusz Dziedzic 	if (!ar->dfs_detector->add_pulse(ar->dfs_detector, &pe)) {
23887aa7a72aSMichal Kazior 		ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
23899702c686SJanusz Dziedzic 			   "dfs no pulse pattern detected, yet\n");
23909702c686SJanusz Dziedzic 		return;
23919702c686SJanusz Dziedzic 	}
23929702c686SJanusz Dziedzic 
23937aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs radar detected\n");
23949702c686SJanusz Dziedzic 	ATH10K_DFS_STAT_INC(ar, radar_detected);
23957d9b40b4SMarek Puzyniak 
23967d9b40b4SMarek Puzyniak 	/* Control radar events reporting in debugfs file
23977d9b40b4SMarek Puzyniak 	   dfs_block_radar_events */
23987d9b40b4SMarek Puzyniak 	if (ar->dfs_block_radar_events) {
23997aa7a72aSMichal Kazior 		ath10k_info(ar, "DFS Radar detected, but ignored as requested\n");
24007d9b40b4SMarek Puzyniak 		return;
24017d9b40b4SMarek Puzyniak 	}
24027d9b40b4SMarek Puzyniak 
24039702c686SJanusz Dziedzic 	ieee80211_radar_detected(ar->hw);
24049702c686SJanusz Dziedzic }
24059702c686SJanusz Dziedzic 
24069702c686SJanusz Dziedzic static int ath10k_dfs_fft_report(struct ath10k *ar,
24072332d0aeSMichal Kazior 				 const struct wmi_phyerr *phyerr,
24082332d0aeSMichal Kazior 				 const struct phyerr_fft_report *fftr,
24099702c686SJanusz Dziedzic 				 u64 tsf)
24109702c686SJanusz Dziedzic {
24119702c686SJanusz Dziedzic 	u32 reg0, reg1;
24129702c686SJanusz Dziedzic 	u8 rssi, peak_mag;
24139702c686SJanusz Dziedzic 
24149702c686SJanusz Dziedzic 	reg0 = __le32_to_cpu(fftr->reg0);
24159702c686SJanusz Dziedzic 	reg1 = __le32_to_cpu(fftr->reg1);
24162332d0aeSMichal Kazior 	rssi = phyerr->rssi_combined;
24179702c686SJanusz Dziedzic 
24187aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
24199702c686SJanusz Dziedzic 		   "wmi phyerr fft report total_gain_db %d base_pwr_db %d fft_chn_idx %d peak_sidx %d\n",
24209702c686SJanusz Dziedzic 		   MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB),
24219702c686SJanusz Dziedzic 		   MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB),
24229702c686SJanusz Dziedzic 		   MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX),
24239702c686SJanusz Dziedzic 		   MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX));
24247aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
24259702c686SJanusz Dziedzic 		   "wmi phyerr fft report rel_pwr_db %d avgpwr_db %d peak_mag %d num_store_bin %d\n",
24269702c686SJanusz Dziedzic 		   MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB),
24279702c686SJanusz Dziedzic 		   MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB),
24289702c686SJanusz Dziedzic 		   MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG),
24299702c686SJanusz Dziedzic 		   MS(reg1, SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB));
24309702c686SJanusz Dziedzic 
24319702c686SJanusz Dziedzic 	peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
24329702c686SJanusz Dziedzic 
24339702c686SJanusz Dziedzic 	/* false event detection */
24349702c686SJanusz Dziedzic 	if (rssi == DFS_RSSI_POSSIBLY_FALSE &&
24359702c686SJanusz Dziedzic 	    peak_mag < 2 * DFS_PEAK_MAG_THOLD_POSSIBLY_FALSE) {
24367aa7a72aSMichal Kazior 		ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs false pulse detected\n");
24379702c686SJanusz Dziedzic 		ATH10K_DFS_STAT_INC(ar, pulses_discarded);
24389702c686SJanusz Dziedzic 		return -EINVAL;
24399702c686SJanusz Dziedzic 	}
24409702c686SJanusz Dziedzic 
24419702c686SJanusz Dziedzic 	return 0;
24429702c686SJanusz Dziedzic }
24439702c686SJanusz Dziedzic 
24440226d602SMichal Kazior void ath10k_wmi_event_dfs(struct ath10k *ar,
24452332d0aeSMichal Kazior 			  const struct wmi_phyerr *phyerr,
24469702c686SJanusz Dziedzic 			  u64 tsf)
24479702c686SJanusz Dziedzic {
24489702c686SJanusz Dziedzic 	int buf_len, tlv_len, res, i = 0;
24492332d0aeSMichal Kazior 	const struct phyerr_tlv *tlv;
24502332d0aeSMichal Kazior 	const struct phyerr_radar_report *rr;
24512332d0aeSMichal Kazior 	const struct phyerr_fft_report *fftr;
24522332d0aeSMichal Kazior 	const u8 *tlv_buf;
24539702c686SJanusz Dziedzic 
24542332d0aeSMichal Kazior 	buf_len = __le32_to_cpu(phyerr->buf_len);
24557aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
24569702c686SJanusz Dziedzic 		   "wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n",
24572332d0aeSMichal Kazior 		   phyerr->phy_err_code, phyerr->rssi_combined,
24582332d0aeSMichal Kazior 		   __le32_to_cpu(phyerr->tsf_timestamp), tsf, buf_len);
24599702c686SJanusz Dziedzic 
24609702c686SJanusz Dziedzic 	/* Skip event if DFS disabled */
24619702c686SJanusz Dziedzic 	if (!config_enabled(CONFIG_ATH10K_DFS_CERTIFIED))
24629702c686SJanusz Dziedzic 		return;
24639702c686SJanusz Dziedzic 
24649702c686SJanusz Dziedzic 	ATH10K_DFS_STAT_INC(ar, pulses_total);
24659702c686SJanusz Dziedzic 
24669702c686SJanusz Dziedzic 	while (i < buf_len) {
24679702c686SJanusz Dziedzic 		if (i + sizeof(*tlv) > buf_len) {
24687aa7a72aSMichal Kazior 			ath10k_warn(ar, "too short buf for tlv header (%d)\n",
24697aa7a72aSMichal Kazior 				    i);
24709702c686SJanusz Dziedzic 			return;
24719702c686SJanusz Dziedzic 		}
24729702c686SJanusz Dziedzic 
24732332d0aeSMichal Kazior 		tlv = (struct phyerr_tlv *)&phyerr->buf[i];
24749702c686SJanusz Dziedzic 		tlv_len = __le16_to_cpu(tlv->len);
24752332d0aeSMichal Kazior 		tlv_buf = &phyerr->buf[i + sizeof(*tlv)];
24767aa7a72aSMichal Kazior 		ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
24779702c686SJanusz Dziedzic 			   "wmi event dfs tlv_len %d tlv_tag 0x%02X tlv_sig 0x%02X\n",
24789702c686SJanusz Dziedzic 			   tlv_len, tlv->tag, tlv->sig);
24799702c686SJanusz Dziedzic 
24809702c686SJanusz Dziedzic 		switch (tlv->tag) {
24819702c686SJanusz Dziedzic 		case PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY:
24829702c686SJanusz Dziedzic 			if (i + sizeof(*tlv) + sizeof(*rr) > buf_len) {
24837aa7a72aSMichal Kazior 				ath10k_warn(ar, "too short radar pulse summary (%d)\n",
24849702c686SJanusz Dziedzic 					    i);
24859702c686SJanusz Dziedzic 				return;
24869702c686SJanusz Dziedzic 			}
24879702c686SJanusz Dziedzic 
24889702c686SJanusz Dziedzic 			rr = (struct phyerr_radar_report *)tlv_buf;
24892332d0aeSMichal Kazior 			ath10k_dfs_radar_report(ar, phyerr, rr, tsf);
24909702c686SJanusz Dziedzic 			break;
24919702c686SJanusz Dziedzic 		case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
24929702c686SJanusz Dziedzic 			if (i + sizeof(*tlv) + sizeof(*fftr) > buf_len) {
24937aa7a72aSMichal Kazior 				ath10k_warn(ar, "too short fft report (%d)\n",
24947aa7a72aSMichal Kazior 					    i);
24959702c686SJanusz Dziedzic 				return;
24969702c686SJanusz Dziedzic 			}
24979702c686SJanusz Dziedzic 
24989702c686SJanusz Dziedzic 			fftr = (struct phyerr_fft_report *)tlv_buf;
24992332d0aeSMichal Kazior 			res = ath10k_dfs_fft_report(ar, phyerr, fftr, tsf);
25009702c686SJanusz Dziedzic 			if (res)
25019702c686SJanusz Dziedzic 				return;
25029702c686SJanusz Dziedzic 			break;
25039702c686SJanusz Dziedzic 		}
25049702c686SJanusz Dziedzic 
25059702c686SJanusz Dziedzic 		i += sizeof(*tlv) + tlv_len;
25069702c686SJanusz Dziedzic 	}
25079702c686SJanusz Dziedzic }
25089702c686SJanusz Dziedzic 
25090226d602SMichal Kazior void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
25102332d0aeSMichal Kazior 				    const struct wmi_phyerr *phyerr,
25119702c686SJanusz Dziedzic 				    u64 tsf)
25129702c686SJanusz Dziedzic {
2513855aed12SSimon Wunderlich 	int buf_len, tlv_len, res, i = 0;
2514855aed12SSimon Wunderlich 	struct phyerr_tlv *tlv;
25152332d0aeSMichal Kazior 	const void *tlv_buf;
25162332d0aeSMichal Kazior 	const struct phyerr_fft_report *fftr;
2517855aed12SSimon Wunderlich 	size_t fftr_len;
2518855aed12SSimon Wunderlich 
25192332d0aeSMichal Kazior 	buf_len = __le32_to_cpu(phyerr->buf_len);
2520855aed12SSimon Wunderlich 
2521855aed12SSimon Wunderlich 	while (i < buf_len) {
2522855aed12SSimon Wunderlich 		if (i + sizeof(*tlv) > buf_len) {
25237aa7a72aSMichal Kazior 			ath10k_warn(ar, "failed to parse phyerr tlv header at byte %d\n",
2524855aed12SSimon Wunderlich 				    i);
2525855aed12SSimon Wunderlich 			return;
2526855aed12SSimon Wunderlich 		}
2527855aed12SSimon Wunderlich 
25282332d0aeSMichal Kazior 		tlv = (struct phyerr_tlv *)&phyerr->buf[i];
2529855aed12SSimon Wunderlich 		tlv_len = __le16_to_cpu(tlv->len);
25302332d0aeSMichal Kazior 		tlv_buf = &phyerr->buf[i + sizeof(*tlv)];
2531855aed12SSimon Wunderlich 
2532855aed12SSimon Wunderlich 		if (i + sizeof(*tlv) + tlv_len > buf_len) {
25337aa7a72aSMichal Kazior 			ath10k_warn(ar, "failed to parse phyerr tlv payload at byte %d\n",
2534855aed12SSimon Wunderlich 				    i);
2535855aed12SSimon Wunderlich 			return;
2536855aed12SSimon Wunderlich 		}
2537855aed12SSimon Wunderlich 
2538855aed12SSimon Wunderlich 		switch (tlv->tag) {
2539855aed12SSimon Wunderlich 		case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
2540855aed12SSimon Wunderlich 			if (sizeof(*fftr) > tlv_len) {
25417aa7a72aSMichal Kazior 				ath10k_warn(ar, "failed to parse fft report at byte %d\n",
2542855aed12SSimon Wunderlich 					    i);
2543855aed12SSimon Wunderlich 				return;
2544855aed12SSimon Wunderlich 			}
2545855aed12SSimon Wunderlich 
2546855aed12SSimon Wunderlich 			fftr_len = tlv_len - sizeof(*fftr);
25472332d0aeSMichal Kazior 			fftr = tlv_buf;
25482332d0aeSMichal Kazior 			res = ath10k_spectral_process_fft(ar, phyerr,
2549855aed12SSimon Wunderlich 							  fftr, fftr_len,
2550855aed12SSimon Wunderlich 							  tsf);
2551855aed12SSimon Wunderlich 			if (res < 0) {
25527aa7a72aSMichal Kazior 				ath10k_warn(ar, "failed to process fft report: %d\n",
2553855aed12SSimon Wunderlich 					    res);
2554855aed12SSimon Wunderlich 				return;
2555855aed12SSimon Wunderlich 			}
2556855aed12SSimon Wunderlich 			break;
2557855aed12SSimon Wunderlich 		}
2558855aed12SSimon Wunderlich 
2559855aed12SSimon Wunderlich 		i += sizeof(*tlv) + tlv_len;
2560855aed12SSimon Wunderlich 	}
25619702c686SJanusz Dziedzic }
25629702c686SJanusz Dziedzic 
2563d7579d12SMichal Kazior static int ath10k_wmi_op_pull_phyerr_ev(struct ath10k *ar, struct sk_buff *skb,
256432653cf1SMichal Kazior 					struct wmi_phyerr_ev_arg *arg)
256532653cf1SMichal Kazior {
256632653cf1SMichal Kazior 	struct wmi_phyerr_event *ev = (void *)skb->data;
256732653cf1SMichal Kazior 
256832653cf1SMichal Kazior 	if (skb->len < sizeof(*ev))
256932653cf1SMichal Kazior 		return -EPROTO;
257032653cf1SMichal Kazior 
257132653cf1SMichal Kazior 	arg->num_phyerrs = ev->num_phyerrs;
257232653cf1SMichal Kazior 	arg->tsf_l32 = ev->tsf_l32;
257332653cf1SMichal Kazior 	arg->tsf_u32 = ev->tsf_u32;
257432653cf1SMichal Kazior 	arg->buf_len = __cpu_to_le32(skb->len - sizeof(*ev));
257532653cf1SMichal Kazior 	arg->phyerrs = ev->phyerrs;
257632653cf1SMichal Kazior 
257732653cf1SMichal Kazior 	return 0;
257832653cf1SMichal Kazior }
257932653cf1SMichal Kazior 
25800226d602SMichal Kazior void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
25815e3dd157SKalle Valo {
258232653cf1SMichal Kazior 	struct wmi_phyerr_ev_arg arg = {};
25832332d0aeSMichal Kazior 	const struct wmi_phyerr *phyerr;
25849702c686SJanusz Dziedzic 	u32 count, i, buf_len, phy_err_code;
25859702c686SJanusz Dziedzic 	u64 tsf;
258632653cf1SMichal Kazior 	int left_len, ret;
25879702c686SJanusz Dziedzic 
25889702c686SJanusz Dziedzic 	ATH10K_DFS_STAT_INC(ar, phy_errors);
25899702c686SJanusz Dziedzic 
2590d7579d12SMichal Kazior 	ret = ath10k_wmi_pull_phyerr(ar, skb, &arg);
259132653cf1SMichal Kazior 	if (ret) {
259232653cf1SMichal Kazior 		ath10k_warn(ar, "failed to parse phyerr event: %d\n", ret);
25939702c686SJanusz Dziedzic 		return;
25949702c686SJanusz Dziedzic 	}
25959702c686SJanusz Dziedzic 
259632653cf1SMichal Kazior 	left_len = __le32_to_cpu(arg.buf_len);
25979702c686SJanusz Dziedzic 
25989702c686SJanusz Dziedzic 	/* Check number of included events */
259932653cf1SMichal Kazior 	count = __le32_to_cpu(arg.num_phyerrs);
26009702c686SJanusz Dziedzic 
260132653cf1SMichal Kazior 	tsf = __le32_to_cpu(arg.tsf_u32);
26029702c686SJanusz Dziedzic 	tsf <<= 32;
260332653cf1SMichal Kazior 	tsf |= __le32_to_cpu(arg.tsf_l32);
26049702c686SJanusz Dziedzic 
26057aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
26069702c686SJanusz Dziedzic 		   "wmi event phyerr count %d tsf64 0x%llX\n",
26079702c686SJanusz Dziedzic 		   count, tsf);
26089702c686SJanusz Dziedzic 
260932653cf1SMichal Kazior 	phyerr = arg.phyerrs;
26109702c686SJanusz Dziedzic 	for (i = 0; i < count; i++) {
26119702c686SJanusz Dziedzic 		/* Check if we can read event header */
26122332d0aeSMichal Kazior 		if (left_len < sizeof(*phyerr)) {
26137aa7a72aSMichal Kazior 			ath10k_warn(ar, "single event (%d) wrong head len\n",
26147aa7a72aSMichal Kazior 				    i);
26159702c686SJanusz Dziedzic 			return;
26169702c686SJanusz Dziedzic 		}
26179702c686SJanusz Dziedzic 
26182332d0aeSMichal Kazior 		left_len -= sizeof(*phyerr);
26199702c686SJanusz Dziedzic 
26202332d0aeSMichal Kazior 		buf_len = __le32_to_cpu(phyerr->buf_len);
26212332d0aeSMichal Kazior 		phy_err_code = phyerr->phy_err_code;
26229702c686SJanusz Dziedzic 
26239702c686SJanusz Dziedzic 		if (left_len < buf_len) {
26247aa7a72aSMichal Kazior 			ath10k_warn(ar, "single event (%d) wrong buf len\n", i);
26259702c686SJanusz Dziedzic 			return;
26269702c686SJanusz Dziedzic 		}
26279702c686SJanusz Dziedzic 
26289702c686SJanusz Dziedzic 		left_len -= buf_len;
26299702c686SJanusz Dziedzic 
26309702c686SJanusz Dziedzic 		switch (phy_err_code) {
26319702c686SJanusz Dziedzic 		case PHY_ERROR_RADAR:
26322332d0aeSMichal Kazior 			ath10k_wmi_event_dfs(ar, phyerr, tsf);
26339702c686SJanusz Dziedzic 			break;
26349702c686SJanusz Dziedzic 		case PHY_ERROR_SPECTRAL_SCAN:
26352332d0aeSMichal Kazior 			ath10k_wmi_event_spectral_scan(ar, phyerr, tsf);
26369702c686SJanusz Dziedzic 			break;
26379702c686SJanusz Dziedzic 		case PHY_ERROR_FALSE_RADAR_EXT:
26382332d0aeSMichal Kazior 			ath10k_wmi_event_dfs(ar, phyerr, tsf);
26392332d0aeSMichal Kazior 			ath10k_wmi_event_spectral_scan(ar, phyerr, tsf);
26409702c686SJanusz Dziedzic 			break;
26419702c686SJanusz Dziedzic 		default:
26429702c686SJanusz Dziedzic 			break;
26439702c686SJanusz Dziedzic 		}
26449702c686SJanusz Dziedzic 
26452332d0aeSMichal Kazior 		phyerr = (void *)phyerr + sizeof(*phyerr) + buf_len;
26469702c686SJanusz Dziedzic 	}
26475e3dd157SKalle Valo }
26485e3dd157SKalle Valo 
26490226d602SMichal Kazior void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb)
26505e3dd157SKalle Valo {
26517aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_ROAM_EVENTID\n");
26525e3dd157SKalle Valo }
26535e3dd157SKalle Valo 
26540226d602SMichal Kazior void ath10k_wmi_event_profile_match(struct ath10k *ar, struct sk_buff *skb)
26555e3dd157SKalle Valo {
26567aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PROFILE_MATCH\n");
26575e3dd157SKalle Valo }
26585e3dd157SKalle Valo 
26590226d602SMichal Kazior void ath10k_wmi_event_debug_print(struct ath10k *ar, struct sk_buff *skb)
26605e3dd157SKalle Valo {
26612fe5288cSKalle Valo 	char buf[101], c;
26622fe5288cSKalle Valo 	int i;
26632fe5288cSKalle Valo 
26642fe5288cSKalle Valo 	for (i = 0; i < sizeof(buf) - 1; i++) {
26652fe5288cSKalle Valo 		if (i >= skb->len)
26662fe5288cSKalle Valo 			break;
26672fe5288cSKalle Valo 
26682fe5288cSKalle Valo 		c = skb->data[i];
26692fe5288cSKalle Valo 
26702fe5288cSKalle Valo 		if (c == '\0')
26712fe5288cSKalle Valo 			break;
26722fe5288cSKalle Valo 
26732fe5288cSKalle Valo 		if (isascii(c) && isprint(c))
26742fe5288cSKalle Valo 			buf[i] = c;
26752fe5288cSKalle Valo 		else
26762fe5288cSKalle Valo 			buf[i] = '.';
26772fe5288cSKalle Valo 	}
26782fe5288cSKalle Valo 
26792fe5288cSKalle Valo 	if (i == sizeof(buf) - 1)
26807aa7a72aSMichal Kazior 		ath10k_warn(ar, "wmi debug print truncated: %d\n", skb->len);
26812fe5288cSKalle Valo 
26822fe5288cSKalle Valo 	/* for some reason the debug prints end with \n, remove that */
26832fe5288cSKalle Valo 	if (skb->data[i - 1] == '\n')
26842fe5288cSKalle Valo 		i--;
26852fe5288cSKalle Valo 
26862fe5288cSKalle Valo 	/* the last byte is always reserved for the null character */
26872fe5288cSKalle Valo 	buf[i] = '\0';
26882fe5288cSKalle Valo 
26893be004c3SBen Greear 	ath10k_dbg(ar, ATH10K_DBG_WMI_PRINT, "wmi print '%s'\n", buf);
26905e3dd157SKalle Valo }
26915e3dd157SKalle Valo 
26920226d602SMichal Kazior void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb)
26935e3dd157SKalle Valo {
26947aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_QVIT_EVENTID\n");
26955e3dd157SKalle Valo }
26965e3dd157SKalle Valo 
26970226d602SMichal Kazior void ath10k_wmi_event_wlan_profile_data(struct ath10k *ar, struct sk_buff *skb)
26985e3dd157SKalle Valo {
26997aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_WLAN_PROFILE_DATA_EVENTID\n");
27005e3dd157SKalle Valo }
27015e3dd157SKalle Valo 
27020226d602SMichal Kazior void ath10k_wmi_event_rtt_measurement_report(struct ath10k *ar,
27035e3dd157SKalle Valo 					     struct sk_buff *skb)
27045e3dd157SKalle Valo {
27057aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_RTT_MEASUREMENT_REPORT_EVENTID\n");
27065e3dd157SKalle Valo }
27075e3dd157SKalle Valo 
27080226d602SMichal Kazior void ath10k_wmi_event_tsf_measurement_report(struct ath10k *ar,
27095e3dd157SKalle Valo 					     struct sk_buff *skb)
27105e3dd157SKalle Valo {
27117aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TSF_MEASUREMENT_REPORT_EVENTID\n");
27125e3dd157SKalle Valo }
27135e3dd157SKalle Valo 
27140226d602SMichal Kazior void ath10k_wmi_event_rtt_error_report(struct ath10k *ar, struct sk_buff *skb)
27155e3dd157SKalle Valo {
27167aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_RTT_ERROR_REPORT_EVENTID\n");
27175e3dd157SKalle Valo }
27185e3dd157SKalle Valo 
27190226d602SMichal Kazior void ath10k_wmi_event_wow_wakeup_host(struct ath10k *ar, struct sk_buff *skb)
27205e3dd157SKalle Valo {
27217aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_WOW_WAKEUP_HOST_EVENTID\n");
27225e3dd157SKalle Valo }
27235e3dd157SKalle Valo 
27240226d602SMichal Kazior void ath10k_wmi_event_dcs_interference(struct ath10k *ar, struct sk_buff *skb)
27255e3dd157SKalle Valo {
27267aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_DCS_INTERFERENCE_EVENTID\n");
27275e3dd157SKalle Valo }
27285e3dd157SKalle Valo 
27290226d602SMichal Kazior void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
27305e3dd157SKalle Valo {
27317aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_TPC_CONFIG_EVENTID\n");
27325e3dd157SKalle Valo }
27335e3dd157SKalle Valo 
27340226d602SMichal Kazior void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, struct sk_buff *skb)
27355e3dd157SKalle Valo {
27367aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_FTM_INTG_EVENTID\n");
27375e3dd157SKalle Valo }
27385e3dd157SKalle Valo 
27390226d602SMichal Kazior void ath10k_wmi_event_gtk_offload_status(struct ath10k *ar, struct sk_buff *skb)
27405e3dd157SKalle Valo {
27417aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_GTK_OFFLOAD_STATUS_EVENTID\n");
27425e3dd157SKalle Valo }
27435e3dd157SKalle Valo 
27440226d602SMichal Kazior void ath10k_wmi_event_gtk_rekey_fail(struct ath10k *ar, struct sk_buff *skb)
27455e3dd157SKalle Valo {
27467aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_GTK_REKEY_FAIL_EVENTID\n");
27475e3dd157SKalle Valo }
27485e3dd157SKalle Valo 
27490226d602SMichal Kazior void ath10k_wmi_event_delba_complete(struct ath10k *ar, struct sk_buff *skb)
27505e3dd157SKalle Valo {
27517aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TX_DELBA_COMPLETE_EVENTID\n");
27525e3dd157SKalle Valo }
27535e3dd157SKalle Valo 
27540226d602SMichal Kazior void ath10k_wmi_event_addba_complete(struct ath10k *ar, struct sk_buff *skb)
27555e3dd157SKalle Valo {
27567aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TX_ADDBA_COMPLETE_EVENTID\n");
27575e3dd157SKalle Valo }
27585e3dd157SKalle Valo 
27590226d602SMichal Kazior void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar,
27605e3dd157SKalle Valo 						struct sk_buff *skb)
27615e3dd157SKalle Valo {
27627aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n");
27635e3dd157SKalle Valo }
27645e3dd157SKalle Valo 
27650226d602SMichal Kazior void ath10k_wmi_event_inst_rssi_stats(struct ath10k *ar, struct sk_buff *skb)
27668a6618b0SBartosz Markowski {
27677aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_INST_RSSI_STATS_EVENTID\n");
27688a6618b0SBartosz Markowski }
27698a6618b0SBartosz Markowski 
27700226d602SMichal Kazior void ath10k_wmi_event_vdev_standby_req(struct ath10k *ar, struct sk_buff *skb)
27718a6618b0SBartosz Markowski {
27727aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_STANDBY_REQ_EVENTID\n");
27738a6618b0SBartosz Markowski }
27748a6618b0SBartosz Markowski 
27750226d602SMichal Kazior void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar, struct sk_buff *skb)
27768a6618b0SBartosz Markowski {
27777aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_RESUME_REQ_EVENTID\n");
27788a6618b0SBartosz Markowski }
27798a6618b0SBartosz Markowski 
2780b3effe61SBartosz Markowski static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
2781b3effe61SBartosz Markowski 				     u32 num_units, u32 unit_len)
2782b3effe61SBartosz Markowski {
2783b3effe61SBartosz Markowski 	dma_addr_t paddr;
2784b3effe61SBartosz Markowski 	u32 pool_size;
2785b3effe61SBartosz Markowski 	int idx = ar->wmi.num_mem_chunks;
2786b3effe61SBartosz Markowski 
2787b3effe61SBartosz Markowski 	pool_size = num_units * round_up(unit_len, 4);
2788b3effe61SBartosz Markowski 
2789b3effe61SBartosz Markowski 	if (!pool_size)
2790b3effe61SBartosz Markowski 		return -EINVAL;
2791b3effe61SBartosz Markowski 
2792b3effe61SBartosz Markowski 	ar->wmi.mem_chunks[idx].vaddr = dma_alloc_coherent(ar->dev,
2793b3effe61SBartosz Markowski 							   pool_size,
2794b3effe61SBartosz Markowski 							   &paddr,
2795b3effe61SBartosz Markowski 							   GFP_ATOMIC);
2796b3effe61SBartosz Markowski 	if (!ar->wmi.mem_chunks[idx].vaddr) {
27977aa7a72aSMichal Kazior 		ath10k_warn(ar, "failed to allocate memory chunk\n");
2798b3effe61SBartosz Markowski 		return -ENOMEM;
2799b3effe61SBartosz Markowski 	}
2800b3effe61SBartosz Markowski 
2801b3effe61SBartosz Markowski 	memset(ar->wmi.mem_chunks[idx].vaddr, 0, pool_size);
2802b3effe61SBartosz Markowski 
2803b3effe61SBartosz Markowski 	ar->wmi.mem_chunks[idx].paddr = paddr;
2804b3effe61SBartosz Markowski 	ar->wmi.mem_chunks[idx].len = pool_size;
2805b3effe61SBartosz Markowski 	ar->wmi.mem_chunks[idx].req_id = req_id;
2806b3effe61SBartosz Markowski 	ar->wmi.num_mem_chunks++;
2807b3effe61SBartosz Markowski 
2808b3effe61SBartosz Markowski 	return 0;
2809b3effe61SBartosz Markowski }
2810b3effe61SBartosz Markowski 
2811d7579d12SMichal Kazior static int
2812d7579d12SMichal Kazior ath10k_wmi_main_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
28135c01aa3dSMichal Kazior 				   struct wmi_svc_rdy_ev_arg *arg)
28145c01aa3dSMichal Kazior {
28155c01aa3dSMichal Kazior 	struct wmi_service_ready_event *ev;
28165c01aa3dSMichal Kazior 	size_t i, n;
28175c01aa3dSMichal Kazior 
28185c01aa3dSMichal Kazior 	if (skb->len < sizeof(*ev))
28195c01aa3dSMichal Kazior 		return -EPROTO;
28205c01aa3dSMichal Kazior 
28215c01aa3dSMichal Kazior 	ev = (void *)skb->data;
28225c01aa3dSMichal Kazior 	skb_pull(skb, sizeof(*ev));
28235c01aa3dSMichal Kazior 	arg->min_tx_power = ev->hw_min_tx_power;
28245c01aa3dSMichal Kazior 	arg->max_tx_power = ev->hw_max_tx_power;
28255c01aa3dSMichal Kazior 	arg->ht_cap = ev->ht_cap_info;
28265c01aa3dSMichal Kazior 	arg->vht_cap = ev->vht_cap_info;
28275c01aa3dSMichal Kazior 	arg->sw_ver0 = ev->sw_version;
28285c01aa3dSMichal Kazior 	arg->sw_ver1 = ev->sw_version_1;
28295c01aa3dSMichal Kazior 	arg->phy_capab = ev->phy_capability;
28305c01aa3dSMichal Kazior 	arg->num_rf_chains = ev->num_rf_chains;
28315c01aa3dSMichal Kazior 	arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
28325c01aa3dSMichal Kazior 	arg->num_mem_reqs = ev->num_mem_reqs;
28335c01aa3dSMichal Kazior 	arg->service_map = ev->wmi_service_bitmap;
28342a3e60d3SMichal Kazior 	arg->service_map_len = sizeof(ev->wmi_service_bitmap);
28355c01aa3dSMichal Kazior 
28365c01aa3dSMichal Kazior 	n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
28375c01aa3dSMichal Kazior 		  ARRAY_SIZE(arg->mem_reqs));
28385c01aa3dSMichal Kazior 	for (i = 0; i < n; i++)
28395c01aa3dSMichal Kazior 		arg->mem_reqs[i] = &ev->mem_reqs[i];
28405c01aa3dSMichal Kazior 
28415c01aa3dSMichal Kazior 	if (skb->len <
28425c01aa3dSMichal Kazior 	    __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0]))
28435c01aa3dSMichal Kazior 		return -EPROTO;
28445c01aa3dSMichal Kazior 
28455c01aa3dSMichal Kazior 	return 0;
28465c01aa3dSMichal Kazior }
28475c01aa3dSMichal Kazior 
2848d7579d12SMichal Kazior static int
2849d7579d12SMichal Kazior ath10k_wmi_10x_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
28505c01aa3dSMichal Kazior 				  struct wmi_svc_rdy_ev_arg *arg)
28515c01aa3dSMichal Kazior {
28525c01aa3dSMichal Kazior 	struct wmi_10x_service_ready_event *ev;
28535c01aa3dSMichal Kazior 	int i, n;
28545c01aa3dSMichal Kazior 
28555c01aa3dSMichal Kazior 	if (skb->len < sizeof(*ev))
28565c01aa3dSMichal Kazior 		return -EPROTO;
28575c01aa3dSMichal Kazior 
28585c01aa3dSMichal Kazior 	ev = (void *)skb->data;
28595c01aa3dSMichal Kazior 	skb_pull(skb, sizeof(*ev));
28605c01aa3dSMichal Kazior 	arg->min_tx_power = ev->hw_min_tx_power;
28615c01aa3dSMichal Kazior 	arg->max_tx_power = ev->hw_max_tx_power;
28625c01aa3dSMichal Kazior 	arg->ht_cap = ev->ht_cap_info;
28635c01aa3dSMichal Kazior 	arg->vht_cap = ev->vht_cap_info;
28645c01aa3dSMichal Kazior 	arg->sw_ver0 = ev->sw_version;
28655c01aa3dSMichal Kazior 	arg->phy_capab = ev->phy_capability;
28665c01aa3dSMichal Kazior 	arg->num_rf_chains = ev->num_rf_chains;
28675c01aa3dSMichal Kazior 	arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
28685c01aa3dSMichal Kazior 	arg->num_mem_reqs = ev->num_mem_reqs;
28695c01aa3dSMichal Kazior 	arg->service_map = ev->wmi_service_bitmap;
28702a3e60d3SMichal Kazior 	arg->service_map_len = sizeof(ev->wmi_service_bitmap);
28715c01aa3dSMichal Kazior 
28725c01aa3dSMichal Kazior 	n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
28735c01aa3dSMichal Kazior 		  ARRAY_SIZE(arg->mem_reqs));
28745c01aa3dSMichal Kazior 	for (i = 0; i < n; i++)
28755c01aa3dSMichal Kazior 		arg->mem_reqs[i] = &ev->mem_reqs[i];
28765c01aa3dSMichal Kazior 
28775c01aa3dSMichal Kazior 	if (skb->len <
28785c01aa3dSMichal Kazior 	    __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0]))
28795c01aa3dSMichal Kazior 		return -EPROTO;
28805c01aa3dSMichal Kazior 
28815c01aa3dSMichal Kazior 	return 0;
28825c01aa3dSMichal Kazior }
28835c01aa3dSMichal Kazior 
28840226d602SMichal Kazior void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb)
28855e3dd157SKalle Valo {
28865c01aa3dSMichal Kazior 	struct wmi_svc_rdy_ev_arg arg = {};
28875c01aa3dSMichal Kazior 	u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
28885c01aa3dSMichal Kazior 	int ret;
28895e3dd157SKalle Valo 
2890d7579d12SMichal Kazior 	ret = ath10k_wmi_pull_svc_rdy(ar, skb, &arg);
28915c01aa3dSMichal Kazior 	if (ret) {
28925c01aa3dSMichal Kazior 		ath10k_warn(ar, "failed to parse service ready: %d\n", ret);
28935e3dd157SKalle Valo 		return;
28945e3dd157SKalle Valo 	}
28955e3dd157SKalle Valo 
2896d7579d12SMichal Kazior 	memset(&ar->wmi.svc_map, 0, sizeof(ar->wmi.svc_map));
2897d7579d12SMichal Kazior 	ath10k_wmi_map_svc(ar, arg.service_map, ar->wmi.svc_map,
2898d7579d12SMichal Kazior 			   arg.service_map_len);
2899d7579d12SMichal Kazior 
29005c01aa3dSMichal Kazior 	ar->hw_min_tx_power = __le32_to_cpu(arg.min_tx_power);
29015c01aa3dSMichal Kazior 	ar->hw_max_tx_power = __le32_to_cpu(arg.max_tx_power);
29025c01aa3dSMichal Kazior 	ar->ht_cap_info = __le32_to_cpu(arg.ht_cap);
29035c01aa3dSMichal Kazior 	ar->vht_cap_info = __le32_to_cpu(arg.vht_cap);
29045e3dd157SKalle Valo 	ar->fw_version_major =
29055c01aa3dSMichal Kazior 		(__le32_to_cpu(arg.sw_ver0) & 0xff000000) >> 24;
29065c01aa3dSMichal Kazior 	ar->fw_version_minor = (__le32_to_cpu(arg.sw_ver0) & 0x00ffffff);
29075e3dd157SKalle Valo 	ar->fw_version_release =
29085c01aa3dSMichal Kazior 		(__le32_to_cpu(arg.sw_ver1) & 0xffff0000) >> 16;
29095c01aa3dSMichal Kazior 	ar->fw_version_build = (__le32_to_cpu(arg.sw_ver1) & 0x0000ffff);
29105c01aa3dSMichal Kazior 	ar->phy_capability = __le32_to_cpu(arg.phy_capab);
29115c01aa3dSMichal Kazior 	ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains);
29125c01aa3dSMichal Kazior 	ar->ath_common.regulatory.current_rd = __le32_to_cpu(arg.eeprom_rd);
29135c01aa3dSMichal Kazior 
29145c01aa3dSMichal Kazior 	ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
29152a3e60d3SMichal Kazior 			arg.service_map, arg.service_map_len);
29168865bee4SMichal Kazior 
29171a222435SKalle Valo 	/* only manually set fw features when not using FW IE format */
29181a222435SKalle Valo 	if (ar->fw_api == 1 && ar->fw_version_build > 636)
29190d9b0438SMichal Kazior 		set_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features);
29200d9b0438SMichal Kazior 
29218865bee4SMichal Kazior 	if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) {
29227aa7a72aSMichal Kazior 		ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n",
29238865bee4SMichal Kazior 			    ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM);
29248865bee4SMichal Kazior 		ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM;
29258865bee4SMichal Kazior 	}
29265e3dd157SKalle Valo 
2927fdb959c7SMichal Kazior 	ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
2928fdb959c7SMichal Kazior 	ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
2929fdb959c7SMichal Kazior 
29305e3dd157SKalle Valo 	if (strlen(ar->hw->wiphy->fw_version) == 0) {
29315e3dd157SKalle Valo 		snprintf(ar->hw->wiphy->fw_version,
29325e3dd157SKalle Valo 			 sizeof(ar->hw->wiphy->fw_version),
29335e3dd157SKalle Valo 			 "%u.%u.%u.%u",
29345e3dd157SKalle Valo 			 ar->fw_version_major,
29355e3dd157SKalle Valo 			 ar->fw_version_minor,
29365e3dd157SKalle Valo 			 ar->fw_version_release,
29375e3dd157SKalle Valo 			 ar->fw_version_build);
29385e3dd157SKalle Valo 	}
29395e3dd157SKalle Valo 
29405c01aa3dSMichal Kazior 	num_mem_reqs = __le32_to_cpu(arg.num_mem_reqs);
29415c01aa3dSMichal Kazior 	if (num_mem_reqs > WMI_MAX_MEM_REQS) {
29427aa7a72aSMichal Kazior 		ath10k_warn(ar, "requested memory chunks number (%d) exceeds the limit\n",
2943b3effe61SBartosz Markowski 			    num_mem_reqs);
2944b3effe61SBartosz Markowski 		return;
29456f97d256SBartosz Markowski 	}
29466f97d256SBartosz Markowski 
2947b3effe61SBartosz Markowski 	for (i = 0; i < num_mem_reqs; ++i) {
29485c01aa3dSMichal Kazior 		req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id);
29495c01aa3dSMichal Kazior 		num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units);
29505c01aa3dSMichal Kazior 		unit_size = __le32_to_cpu(arg.mem_reqs[i]->unit_size);
29515c01aa3dSMichal Kazior 		num_unit_info = __le32_to_cpu(arg.mem_reqs[i]->num_unit_info);
2952b3effe61SBartosz Markowski 
2953b3effe61SBartosz Markowski 		if (num_unit_info & NUM_UNITS_IS_NUM_PEERS)
2954b3effe61SBartosz Markowski 			/* number of units to allocate is number of
2955b3effe61SBartosz Markowski 			 * peers, 1 extra for self peer on target */
2956b3effe61SBartosz Markowski 			/* this needs to be tied, host and target
2957b3effe61SBartosz Markowski 			 * can get out of sync */
2958ec6a73f0SBartosz Markowski 			num_units = TARGET_10X_NUM_PEERS + 1;
2959b3effe61SBartosz Markowski 		else if (num_unit_info & NUM_UNITS_IS_NUM_VDEVS)
2960ec6a73f0SBartosz Markowski 			num_units = TARGET_10X_NUM_VDEVS + 1;
2961b3effe61SBartosz Markowski 
29627aa7a72aSMichal Kazior 		ath10k_dbg(ar, ATH10K_DBG_WMI,
2963b3effe61SBartosz Markowski 			   "wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n",
2964b3effe61SBartosz Markowski 			   req_id,
29655c01aa3dSMichal Kazior 			   __le32_to_cpu(arg.mem_reqs[i]->num_units),
2966b3effe61SBartosz Markowski 			   num_unit_info,
2967b3effe61SBartosz Markowski 			   unit_size,
2968b3effe61SBartosz Markowski 			   num_units);
2969b3effe61SBartosz Markowski 
2970b3effe61SBartosz Markowski 		ret = ath10k_wmi_alloc_host_mem(ar, req_id, num_units,
2971b3effe61SBartosz Markowski 						unit_size);
2972b3effe61SBartosz Markowski 		if (ret)
2973b3effe61SBartosz Markowski 			return;
2974b3effe61SBartosz Markowski 	}
2975b3effe61SBartosz Markowski 
29767aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
2977ca996ec5SMichal Kazior 		   "wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x fw_build 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n",
29785c01aa3dSMichal Kazior 		   __le32_to_cpu(arg.min_tx_power),
29795c01aa3dSMichal Kazior 		   __le32_to_cpu(arg.max_tx_power),
29805c01aa3dSMichal Kazior 		   __le32_to_cpu(arg.ht_cap),
29815c01aa3dSMichal Kazior 		   __le32_to_cpu(arg.vht_cap),
29825c01aa3dSMichal Kazior 		   __le32_to_cpu(arg.sw_ver0),
29835c01aa3dSMichal Kazior 		   __le32_to_cpu(arg.sw_ver1),
2984ca996ec5SMichal Kazior 		   __le32_to_cpu(arg.fw_build),
29855c01aa3dSMichal Kazior 		   __le32_to_cpu(arg.phy_capab),
29865c01aa3dSMichal Kazior 		   __le32_to_cpu(arg.num_rf_chains),
29875c01aa3dSMichal Kazior 		   __le32_to_cpu(arg.eeprom_rd),
29885c01aa3dSMichal Kazior 		   __le32_to_cpu(arg.num_mem_reqs));
29896f97d256SBartosz Markowski 
29906f97d256SBartosz Markowski 	complete(&ar->wmi.service_ready);
29916f97d256SBartosz Markowski }
29926f97d256SBartosz Markowski 
2993d7579d12SMichal Kazior static int ath10k_wmi_op_pull_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
299432653cf1SMichal Kazior 				     struct wmi_rdy_ev_arg *arg)
299532653cf1SMichal Kazior {
299632653cf1SMichal Kazior 	struct wmi_ready_event *ev = (void *)skb->data;
299732653cf1SMichal Kazior 
299832653cf1SMichal Kazior 	if (skb->len < sizeof(*ev))
299932653cf1SMichal Kazior 		return -EPROTO;
300032653cf1SMichal Kazior 
300132653cf1SMichal Kazior 	skb_pull(skb, sizeof(*ev));
300232653cf1SMichal Kazior 	arg->sw_version = ev->sw_version;
300332653cf1SMichal Kazior 	arg->abi_version = ev->abi_version;
300432653cf1SMichal Kazior 	arg->status = ev->status;
300532653cf1SMichal Kazior 	arg->mac_addr = ev->mac_addr.addr;
300632653cf1SMichal Kazior 
300732653cf1SMichal Kazior 	return 0;
300832653cf1SMichal Kazior }
300932653cf1SMichal Kazior 
30100226d602SMichal Kazior int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
30115e3dd157SKalle Valo {
301232653cf1SMichal Kazior 	struct wmi_rdy_ev_arg arg = {};
301332653cf1SMichal Kazior 	int ret;
30145e3dd157SKalle Valo 
3015d7579d12SMichal Kazior 	ret = ath10k_wmi_pull_rdy(ar, skb, &arg);
301632653cf1SMichal Kazior 	if (ret) {
301732653cf1SMichal Kazior 		ath10k_warn(ar, "failed to parse ready event: %d\n", ret);
301832653cf1SMichal Kazior 		return ret;
301932653cf1SMichal Kazior 	}
30205e3dd157SKalle Valo 
30217aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
302232653cf1SMichal Kazior 		   "wmi event ready sw_version %u abi_version %u mac_addr %pM status %d\n",
302332653cf1SMichal Kazior 		   __le32_to_cpu(arg.sw_version),
302432653cf1SMichal Kazior 		   __le32_to_cpu(arg.abi_version),
302532653cf1SMichal Kazior 		   arg.mac_addr,
302632653cf1SMichal Kazior 		   __le32_to_cpu(arg.status));
30275e3dd157SKalle Valo 
302832653cf1SMichal Kazior 	ether_addr_copy(ar->mac_addr, arg.mac_addr);
30295e3dd157SKalle Valo 	complete(&ar->wmi.unified_ready);
30305e3dd157SKalle Valo 	return 0;
30315e3dd157SKalle Valo }
30325e3dd157SKalle Valo 
3033a57a6a27SRajkumar Manoharan static int ath10k_wmi_event_temperature(struct ath10k *ar, struct sk_buff *skb)
3034a57a6a27SRajkumar Manoharan {
3035a57a6a27SRajkumar Manoharan 	const struct wmi_pdev_temperature_event *ev;
3036a57a6a27SRajkumar Manoharan 
3037a57a6a27SRajkumar Manoharan 	ev = (struct wmi_pdev_temperature_event *)skb->data;
3038a57a6a27SRajkumar Manoharan 	if (WARN_ON(skb->len < sizeof(*ev)))
3039a57a6a27SRajkumar Manoharan 		return -EPROTO;
3040a57a6a27SRajkumar Manoharan 
3041ac2953fcSRajkumar Manoharan 	ath10k_thermal_event_temperature(ar, __le32_to_cpu(ev->temperature));
3042a57a6a27SRajkumar Manoharan 	return 0;
3043a57a6a27SRajkumar Manoharan }
3044a57a6a27SRajkumar Manoharan 
3045d7579d12SMichal Kazior static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb)
30465e3dd157SKalle Valo {
30475e3dd157SKalle Valo 	struct wmi_cmd_hdr *cmd_hdr;
30485e3dd157SKalle Valo 	enum wmi_event_id id;
30495e3dd157SKalle Valo 
30505e3dd157SKalle Valo 	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
30515e3dd157SKalle Valo 	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
30525e3dd157SKalle Valo 
30535e3dd157SKalle Valo 	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
30545e3dd157SKalle Valo 		return;
30555e3dd157SKalle Valo 
3056d35a6c18SMichal Kazior 	trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
30575e3dd157SKalle Valo 
30585e3dd157SKalle Valo 	switch (id) {
30595e3dd157SKalle Valo 	case WMI_MGMT_RX_EVENTID:
30605e3dd157SKalle Valo 		ath10k_wmi_event_mgmt_rx(ar, skb);
30615e3dd157SKalle Valo 		/* mgmt_rx() owns the skb now! */
30625e3dd157SKalle Valo 		return;
30635e3dd157SKalle Valo 	case WMI_SCAN_EVENTID:
30645e3dd157SKalle Valo 		ath10k_wmi_event_scan(ar, skb);
30655e3dd157SKalle Valo 		break;
30665e3dd157SKalle Valo 	case WMI_CHAN_INFO_EVENTID:
30675e3dd157SKalle Valo 		ath10k_wmi_event_chan_info(ar, skb);
30685e3dd157SKalle Valo 		break;
30695e3dd157SKalle Valo 	case WMI_ECHO_EVENTID:
30705e3dd157SKalle Valo 		ath10k_wmi_event_echo(ar, skb);
30715e3dd157SKalle Valo 		break;
30725e3dd157SKalle Valo 	case WMI_DEBUG_MESG_EVENTID:
30735e3dd157SKalle Valo 		ath10k_wmi_event_debug_mesg(ar, skb);
30745e3dd157SKalle Valo 		break;
30755e3dd157SKalle Valo 	case WMI_UPDATE_STATS_EVENTID:
30765e3dd157SKalle Valo 		ath10k_wmi_event_update_stats(ar, skb);
30775e3dd157SKalle Valo 		break;
30785e3dd157SKalle Valo 	case WMI_VDEV_START_RESP_EVENTID:
30795e3dd157SKalle Valo 		ath10k_wmi_event_vdev_start_resp(ar, skb);
30805e3dd157SKalle Valo 		break;
30815e3dd157SKalle Valo 	case WMI_VDEV_STOPPED_EVENTID:
30825e3dd157SKalle Valo 		ath10k_wmi_event_vdev_stopped(ar, skb);
30835e3dd157SKalle Valo 		break;
30845e3dd157SKalle Valo 	case WMI_PEER_STA_KICKOUT_EVENTID:
30855e3dd157SKalle Valo 		ath10k_wmi_event_peer_sta_kickout(ar, skb);
30865e3dd157SKalle Valo 		break;
30875e3dd157SKalle Valo 	case WMI_HOST_SWBA_EVENTID:
30885e3dd157SKalle Valo 		ath10k_wmi_event_host_swba(ar, skb);
30895e3dd157SKalle Valo 		break;
30905e3dd157SKalle Valo 	case WMI_TBTTOFFSET_UPDATE_EVENTID:
30915e3dd157SKalle Valo 		ath10k_wmi_event_tbttoffset_update(ar, skb);
30925e3dd157SKalle Valo 		break;
30935e3dd157SKalle Valo 	case WMI_PHYERR_EVENTID:
30945e3dd157SKalle Valo 		ath10k_wmi_event_phyerr(ar, skb);
30955e3dd157SKalle Valo 		break;
30965e3dd157SKalle Valo 	case WMI_ROAM_EVENTID:
30975e3dd157SKalle Valo 		ath10k_wmi_event_roam(ar, skb);
30985e3dd157SKalle Valo 		break;
30995e3dd157SKalle Valo 	case WMI_PROFILE_MATCH:
31005e3dd157SKalle Valo 		ath10k_wmi_event_profile_match(ar, skb);
31015e3dd157SKalle Valo 		break;
31025e3dd157SKalle Valo 	case WMI_DEBUG_PRINT_EVENTID:
31035e3dd157SKalle Valo 		ath10k_wmi_event_debug_print(ar, skb);
31045e3dd157SKalle Valo 		break;
31055e3dd157SKalle Valo 	case WMI_PDEV_QVIT_EVENTID:
31065e3dd157SKalle Valo 		ath10k_wmi_event_pdev_qvit(ar, skb);
31075e3dd157SKalle Valo 		break;
31085e3dd157SKalle Valo 	case WMI_WLAN_PROFILE_DATA_EVENTID:
31095e3dd157SKalle Valo 		ath10k_wmi_event_wlan_profile_data(ar, skb);
31105e3dd157SKalle Valo 		break;
31115e3dd157SKalle Valo 	case WMI_RTT_MEASUREMENT_REPORT_EVENTID:
31125e3dd157SKalle Valo 		ath10k_wmi_event_rtt_measurement_report(ar, skb);
31135e3dd157SKalle Valo 		break;
31145e3dd157SKalle Valo 	case WMI_TSF_MEASUREMENT_REPORT_EVENTID:
31155e3dd157SKalle Valo 		ath10k_wmi_event_tsf_measurement_report(ar, skb);
31165e3dd157SKalle Valo 		break;
31175e3dd157SKalle Valo 	case WMI_RTT_ERROR_REPORT_EVENTID:
31185e3dd157SKalle Valo 		ath10k_wmi_event_rtt_error_report(ar, skb);
31195e3dd157SKalle Valo 		break;
31205e3dd157SKalle Valo 	case WMI_WOW_WAKEUP_HOST_EVENTID:
31215e3dd157SKalle Valo 		ath10k_wmi_event_wow_wakeup_host(ar, skb);
31225e3dd157SKalle Valo 		break;
31235e3dd157SKalle Valo 	case WMI_DCS_INTERFERENCE_EVENTID:
31245e3dd157SKalle Valo 		ath10k_wmi_event_dcs_interference(ar, skb);
31255e3dd157SKalle Valo 		break;
31265e3dd157SKalle Valo 	case WMI_PDEV_TPC_CONFIG_EVENTID:
31275e3dd157SKalle Valo 		ath10k_wmi_event_pdev_tpc_config(ar, skb);
31285e3dd157SKalle Valo 		break;
31295e3dd157SKalle Valo 	case WMI_PDEV_FTM_INTG_EVENTID:
31305e3dd157SKalle Valo 		ath10k_wmi_event_pdev_ftm_intg(ar, skb);
31315e3dd157SKalle Valo 		break;
31325e3dd157SKalle Valo 	case WMI_GTK_OFFLOAD_STATUS_EVENTID:
31335e3dd157SKalle Valo 		ath10k_wmi_event_gtk_offload_status(ar, skb);
31345e3dd157SKalle Valo 		break;
31355e3dd157SKalle Valo 	case WMI_GTK_REKEY_FAIL_EVENTID:
31365e3dd157SKalle Valo 		ath10k_wmi_event_gtk_rekey_fail(ar, skb);
31375e3dd157SKalle Valo 		break;
31385e3dd157SKalle Valo 	case WMI_TX_DELBA_COMPLETE_EVENTID:
31395e3dd157SKalle Valo 		ath10k_wmi_event_delba_complete(ar, skb);
31405e3dd157SKalle Valo 		break;
31415e3dd157SKalle Valo 	case WMI_TX_ADDBA_COMPLETE_EVENTID:
31425e3dd157SKalle Valo 		ath10k_wmi_event_addba_complete(ar, skb);
31435e3dd157SKalle Valo 		break;
31445e3dd157SKalle Valo 	case WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID:
31455e3dd157SKalle Valo 		ath10k_wmi_event_vdev_install_key_complete(ar, skb);
31465e3dd157SKalle Valo 		break;
31475e3dd157SKalle Valo 	case WMI_SERVICE_READY_EVENTID:
3148b34d2b3dSMichal Kazior 		ath10k_wmi_event_service_ready(ar, skb);
31495e3dd157SKalle Valo 		break;
31505e3dd157SKalle Valo 	case WMI_READY_EVENTID:
3151b34d2b3dSMichal Kazior 		ath10k_wmi_event_ready(ar, skb);
31525e3dd157SKalle Valo 		break;
31535e3dd157SKalle Valo 	default:
31547aa7a72aSMichal Kazior 		ath10k_warn(ar, "Unknown eventid: %d\n", id);
31555e3dd157SKalle Valo 		break;
31565e3dd157SKalle Valo 	}
31575e3dd157SKalle Valo 
31585e3dd157SKalle Valo 	dev_kfree_skb(skb);
31595e3dd157SKalle Valo }
31605e3dd157SKalle Valo 
3161d7579d12SMichal Kazior static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb)
31628a6618b0SBartosz Markowski {
31638a6618b0SBartosz Markowski 	struct wmi_cmd_hdr *cmd_hdr;
31648a6618b0SBartosz Markowski 	enum wmi_10x_event_id id;
316543d2a30fSKalle Valo 	bool consumed;
31668a6618b0SBartosz Markowski 
31678a6618b0SBartosz Markowski 	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
31688a6618b0SBartosz Markowski 	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
31698a6618b0SBartosz Markowski 
31708a6618b0SBartosz Markowski 	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
31718a6618b0SBartosz Markowski 		return;
31728a6618b0SBartosz Markowski 
3173d35a6c18SMichal Kazior 	trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
31748a6618b0SBartosz Markowski 
317543d2a30fSKalle Valo 	consumed = ath10k_tm_event_wmi(ar, id, skb);
317643d2a30fSKalle Valo 
317743d2a30fSKalle Valo 	/* Ready event must be handled normally also in UTF mode so that we
317843d2a30fSKalle Valo 	 * know the UTF firmware has booted, others we are just bypass WMI
317943d2a30fSKalle Valo 	 * events to testmode.
318043d2a30fSKalle Valo 	 */
318143d2a30fSKalle Valo 	if (consumed && id != WMI_10X_READY_EVENTID) {
318243d2a30fSKalle Valo 		ath10k_dbg(ar, ATH10K_DBG_WMI,
318343d2a30fSKalle Valo 			   "wmi testmode consumed 0x%x\n", id);
318443d2a30fSKalle Valo 		goto out;
318543d2a30fSKalle Valo 	}
318643d2a30fSKalle Valo 
31878a6618b0SBartosz Markowski 	switch (id) {
31888a6618b0SBartosz Markowski 	case WMI_10X_MGMT_RX_EVENTID:
31898a6618b0SBartosz Markowski 		ath10k_wmi_event_mgmt_rx(ar, skb);
31908a6618b0SBartosz Markowski 		/* mgmt_rx() owns the skb now! */
31918a6618b0SBartosz Markowski 		return;
31928a6618b0SBartosz Markowski 	case WMI_10X_SCAN_EVENTID:
31938a6618b0SBartosz Markowski 		ath10k_wmi_event_scan(ar, skb);
31948a6618b0SBartosz Markowski 		break;
31958a6618b0SBartosz Markowski 	case WMI_10X_CHAN_INFO_EVENTID:
31968a6618b0SBartosz Markowski 		ath10k_wmi_event_chan_info(ar, skb);
31978a6618b0SBartosz Markowski 		break;
31988a6618b0SBartosz Markowski 	case WMI_10X_ECHO_EVENTID:
31998a6618b0SBartosz Markowski 		ath10k_wmi_event_echo(ar, skb);
32008a6618b0SBartosz Markowski 		break;
32018a6618b0SBartosz Markowski 	case WMI_10X_DEBUG_MESG_EVENTID:
32028a6618b0SBartosz Markowski 		ath10k_wmi_event_debug_mesg(ar, skb);
32038a6618b0SBartosz Markowski 		break;
32048a6618b0SBartosz Markowski 	case WMI_10X_UPDATE_STATS_EVENTID:
32058a6618b0SBartosz Markowski 		ath10k_wmi_event_update_stats(ar, skb);
32068a6618b0SBartosz Markowski 		break;
32078a6618b0SBartosz Markowski 	case WMI_10X_VDEV_START_RESP_EVENTID:
32088a6618b0SBartosz Markowski 		ath10k_wmi_event_vdev_start_resp(ar, skb);
32098a6618b0SBartosz Markowski 		break;
32108a6618b0SBartosz Markowski 	case WMI_10X_VDEV_STOPPED_EVENTID:
32118a6618b0SBartosz Markowski 		ath10k_wmi_event_vdev_stopped(ar, skb);
32128a6618b0SBartosz Markowski 		break;
32138a6618b0SBartosz Markowski 	case WMI_10X_PEER_STA_KICKOUT_EVENTID:
32148a6618b0SBartosz Markowski 		ath10k_wmi_event_peer_sta_kickout(ar, skb);
32158a6618b0SBartosz Markowski 		break;
32168a6618b0SBartosz Markowski 	case WMI_10X_HOST_SWBA_EVENTID:
32178a6618b0SBartosz Markowski 		ath10k_wmi_event_host_swba(ar, skb);
32188a6618b0SBartosz Markowski 		break;
32198a6618b0SBartosz Markowski 	case WMI_10X_TBTTOFFSET_UPDATE_EVENTID:
32208a6618b0SBartosz Markowski 		ath10k_wmi_event_tbttoffset_update(ar, skb);
32218a6618b0SBartosz Markowski 		break;
32228a6618b0SBartosz Markowski 	case WMI_10X_PHYERR_EVENTID:
32238a6618b0SBartosz Markowski 		ath10k_wmi_event_phyerr(ar, skb);
32248a6618b0SBartosz Markowski 		break;
32258a6618b0SBartosz Markowski 	case WMI_10X_ROAM_EVENTID:
32268a6618b0SBartosz Markowski 		ath10k_wmi_event_roam(ar, skb);
32278a6618b0SBartosz Markowski 		break;
32288a6618b0SBartosz Markowski 	case WMI_10X_PROFILE_MATCH:
32298a6618b0SBartosz Markowski 		ath10k_wmi_event_profile_match(ar, skb);
32308a6618b0SBartosz Markowski 		break;
32318a6618b0SBartosz Markowski 	case WMI_10X_DEBUG_PRINT_EVENTID:
32328a6618b0SBartosz Markowski 		ath10k_wmi_event_debug_print(ar, skb);
32338a6618b0SBartosz Markowski 		break;
32348a6618b0SBartosz Markowski 	case WMI_10X_PDEV_QVIT_EVENTID:
32358a6618b0SBartosz Markowski 		ath10k_wmi_event_pdev_qvit(ar, skb);
32368a6618b0SBartosz Markowski 		break;
32378a6618b0SBartosz Markowski 	case WMI_10X_WLAN_PROFILE_DATA_EVENTID:
32388a6618b0SBartosz Markowski 		ath10k_wmi_event_wlan_profile_data(ar, skb);
32398a6618b0SBartosz Markowski 		break;
32408a6618b0SBartosz Markowski 	case WMI_10X_RTT_MEASUREMENT_REPORT_EVENTID:
32418a6618b0SBartosz Markowski 		ath10k_wmi_event_rtt_measurement_report(ar, skb);
32428a6618b0SBartosz Markowski 		break;
32438a6618b0SBartosz Markowski 	case WMI_10X_TSF_MEASUREMENT_REPORT_EVENTID:
32448a6618b0SBartosz Markowski 		ath10k_wmi_event_tsf_measurement_report(ar, skb);
32458a6618b0SBartosz Markowski 		break;
32468a6618b0SBartosz Markowski 	case WMI_10X_RTT_ERROR_REPORT_EVENTID:
32478a6618b0SBartosz Markowski 		ath10k_wmi_event_rtt_error_report(ar, skb);
32488a6618b0SBartosz Markowski 		break;
32498a6618b0SBartosz Markowski 	case WMI_10X_WOW_WAKEUP_HOST_EVENTID:
32508a6618b0SBartosz Markowski 		ath10k_wmi_event_wow_wakeup_host(ar, skb);
32518a6618b0SBartosz Markowski 		break;
32528a6618b0SBartosz Markowski 	case WMI_10X_DCS_INTERFERENCE_EVENTID:
32538a6618b0SBartosz Markowski 		ath10k_wmi_event_dcs_interference(ar, skb);
32548a6618b0SBartosz Markowski 		break;
32558a6618b0SBartosz Markowski 	case WMI_10X_PDEV_TPC_CONFIG_EVENTID:
32568a6618b0SBartosz Markowski 		ath10k_wmi_event_pdev_tpc_config(ar, skb);
32578a6618b0SBartosz Markowski 		break;
32588a6618b0SBartosz Markowski 	case WMI_10X_INST_RSSI_STATS_EVENTID:
32598a6618b0SBartosz Markowski 		ath10k_wmi_event_inst_rssi_stats(ar, skb);
32608a6618b0SBartosz Markowski 		break;
32618a6618b0SBartosz Markowski 	case WMI_10X_VDEV_STANDBY_REQ_EVENTID:
32628a6618b0SBartosz Markowski 		ath10k_wmi_event_vdev_standby_req(ar, skb);
32638a6618b0SBartosz Markowski 		break;
32648a6618b0SBartosz Markowski 	case WMI_10X_VDEV_RESUME_REQ_EVENTID:
32658a6618b0SBartosz Markowski 		ath10k_wmi_event_vdev_resume_req(ar, skb);
32668a6618b0SBartosz Markowski 		break;
32678a6618b0SBartosz Markowski 	case WMI_10X_SERVICE_READY_EVENTID:
3268b34d2b3dSMichal Kazior 		ath10k_wmi_event_service_ready(ar, skb);
32698a6618b0SBartosz Markowski 		break;
32708a6618b0SBartosz Markowski 	case WMI_10X_READY_EVENTID:
3271b34d2b3dSMichal Kazior 		ath10k_wmi_event_ready(ar, skb);
32728a6618b0SBartosz Markowski 		break;
327343d2a30fSKalle Valo 	case WMI_10X_PDEV_UTF_EVENTID:
327443d2a30fSKalle Valo 		/* ignore utf events */
327543d2a30fSKalle Valo 		break;
32768a6618b0SBartosz Markowski 	default:
32777aa7a72aSMichal Kazior 		ath10k_warn(ar, "Unknown eventid: %d\n", id);
32788a6618b0SBartosz Markowski 		break;
32798a6618b0SBartosz Markowski 	}
32808a6618b0SBartosz Markowski 
328143d2a30fSKalle Valo out:
32828a6618b0SBartosz Markowski 	dev_kfree_skb(skb);
32838a6618b0SBartosz Markowski }
32848a6618b0SBartosz Markowski 
3285d7579d12SMichal Kazior static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb)
328624c88f78SMichal Kazior {
328724c88f78SMichal Kazior 	struct wmi_cmd_hdr *cmd_hdr;
328824c88f78SMichal Kazior 	enum wmi_10_2_event_id id;
328924c88f78SMichal Kazior 
329024c88f78SMichal Kazior 	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
329124c88f78SMichal Kazior 	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
329224c88f78SMichal Kazior 
329324c88f78SMichal Kazior 	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
329424c88f78SMichal Kazior 		return;
329524c88f78SMichal Kazior 
3296d35a6c18SMichal Kazior 	trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
329724c88f78SMichal Kazior 
329824c88f78SMichal Kazior 	switch (id) {
329924c88f78SMichal Kazior 	case WMI_10_2_MGMT_RX_EVENTID:
330024c88f78SMichal Kazior 		ath10k_wmi_event_mgmt_rx(ar, skb);
330124c88f78SMichal Kazior 		/* mgmt_rx() owns the skb now! */
330224c88f78SMichal Kazior 		return;
330324c88f78SMichal Kazior 	case WMI_10_2_SCAN_EVENTID:
330424c88f78SMichal Kazior 		ath10k_wmi_event_scan(ar, skb);
330524c88f78SMichal Kazior 		break;
330624c88f78SMichal Kazior 	case WMI_10_2_CHAN_INFO_EVENTID:
330724c88f78SMichal Kazior 		ath10k_wmi_event_chan_info(ar, skb);
330824c88f78SMichal Kazior 		break;
330924c88f78SMichal Kazior 	case WMI_10_2_ECHO_EVENTID:
331024c88f78SMichal Kazior 		ath10k_wmi_event_echo(ar, skb);
331124c88f78SMichal Kazior 		break;
331224c88f78SMichal Kazior 	case WMI_10_2_DEBUG_MESG_EVENTID:
331324c88f78SMichal Kazior 		ath10k_wmi_event_debug_mesg(ar, skb);
331424c88f78SMichal Kazior 		break;
331524c88f78SMichal Kazior 	case WMI_10_2_UPDATE_STATS_EVENTID:
331624c88f78SMichal Kazior 		ath10k_wmi_event_update_stats(ar, skb);
331724c88f78SMichal Kazior 		break;
331824c88f78SMichal Kazior 	case WMI_10_2_VDEV_START_RESP_EVENTID:
331924c88f78SMichal Kazior 		ath10k_wmi_event_vdev_start_resp(ar, skb);
332024c88f78SMichal Kazior 		break;
332124c88f78SMichal Kazior 	case WMI_10_2_VDEV_STOPPED_EVENTID:
332224c88f78SMichal Kazior 		ath10k_wmi_event_vdev_stopped(ar, skb);
332324c88f78SMichal Kazior 		break;
332424c88f78SMichal Kazior 	case WMI_10_2_PEER_STA_KICKOUT_EVENTID:
332524c88f78SMichal Kazior 		ath10k_wmi_event_peer_sta_kickout(ar, skb);
332624c88f78SMichal Kazior 		break;
332724c88f78SMichal Kazior 	case WMI_10_2_HOST_SWBA_EVENTID:
332824c88f78SMichal Kazior 		ath10k_wmi_event_host_swba(ar, skb);
332924c88f78SMichal Kazior 		break;
333024c88f78SMichal Kazior 	case WMI_10_2_TBTTOFFSET_UPDATE_EVENTID:
333124c88f78SMichal Kazior 		ath10k_wmi_event_tbttoffset_update(ar, skb);
333224c88f78SMichal Kazior 		break;
333324c88f78SMichal Kazior 	case WMI_10_2_PHYERR_EVENTID:
333424c88f78SMichal Kazior 		ath10k_wmi_event_phyerr(ar, skb);
333524c88f78SMichal Kazior 		break;
333624c88f78SMichal Kazior 	case WMI_10_2_ROAM_EVENTID:
333724c88f78SMichal Kazior 		ath10k_wmi_event_roam(ar, skb);
333824c88f78SMichal Kazior 		break;
333924c88f78SMichal Kazior 	case WMI_10_2_PROFILE_MATCH:
334024c88f78SMichal Kazior 		ath10k_wmi_event_profile_match(ar, skb);
334124c88f78SMichal Kazior 		break;
334224c88f78SMichal Kazior 	case WMI_10_2_DEBUG_PRINT_EVENTID:
334324c88f78SMichal Kazior 		ath10k_wmi_event_debug_print(ar, skb);
334424c88f78SMichal Kazior 		break;
334524c88f78SMichal Kazior 	case WMI_10_2_PDEV_QVIT_EVENTID:
334624c88f78SMichal Kazior 		ath10k_wmi_event_pdev_qvit(ar, skb);
334724c88f78SMichal Kazior 		break;
334824c88f78SMichal Kazior 	case WMI_10_2_WLAN_PROFILE_DATA_EVENTID:
334924c88f78SMichal Kazior 		ath10k_wmi_event_wlan_profile_data(ar, skb);
335024c88f78SMichal Kazior 		break;
335124c88f78SMichal Kazior 	case WMI_10_2_RTT_MEASUREMENT_REPORT_EVENTID:
335224c88f78SMichal Kazior 		ath10k_wmi_event_rtt_measurement_report(ar, skb);
335324c88f78SMichal Kazior 		break;
335424c88f78SMichal Kazior 	case WMI_10_2_TSF_MEASUREMENT_REPORT_EVENTID:
335524c88f78SMichal Kazior 		ath10k_wmi_event_tsf_measurement_report(ar, skb);
335624c88f78SMichal Kazior 		break;
335724c88f78SMichal Kazior 	case WMI_10_2_RTT_ERROR_REPORT_EVENTID:
335824c88f78SMichal Kazior 		ath10k_wmi_event_rtt_error_report(ar, skb);
335924c88f78SMichal Kazior 		break;
336024c88f78SMichal Kazior 	case WMI_10_2_WOW_WAKEUP_HOST_EVENTID:
336124c88f78SMichal Kazior 		ath10k_wmi_event_wow_wakeup_host(ar, skb);
336224c88f78SMichal Kazior 		break;
336324c88f78SMichal Kazior 	case WMI_10_2_DCS_INTERFERENCE_EVENTID:
336424c88f78SMichal Kazior 		ath10k_wmi_event_dcs_interference(ar, skb);
336524c88f78SMichal Kazior 		break;
336624c88f78SMichal Kazior 	case WMI_10_2_PDEV_TPC_CONFIG_EVENTID:
336724c88f78SMichal Kazior 		ath10k_wmi_event_pdev_tpc_config(ar, skb);
336824c88f78SMichal Kazior 		break;
336924c88f78SMichal Kazior 	case WMI_10_2_INST_RSSI_STATS_EVENTID:
337024c88f78SMichal Kazior 		ath10k_wmi_event_inst_rssi_stats(ar, skb);
337124c88f78SMichal Kazior 		break;
337224c88f78SMichal Kazior 	case WMI_10_2_VDEV_STANDBY_REQ_EVENTID:
337324c88f78SMichal Kazior 		ath10k_wmi_event_vdev_standby_req(ar, skb);
337424c88f78SMichal Kazior 		break;
337524c88f78SMichal Kazior 	case WMI_10_2_VDEV_RESUME_REQ_EVENTID:
337624c88f78SMichal Kazior 		ath10k_wmi_event_vdev_resume_req(ar, skb);
337724c88f78SMichal Kazior 		break;
337824c88f78SMichal Kazior 	case WMI_10_2_SERVICE_READY_EVENTID:
3379b34d2b3dSMichal Kazior 		ath10k_wmi_event_service_ready(ar, skb);
338024c88f78SMichal Kazior 		break;
338124c88f78SMichal Kazior 	case WMI_10_2_READY_EVENTID:
3382b34d2b3dSMichal Kazior 		ath10k_wmi_event_ready(ar, skb);
338324c88f78SMichal Kazior 		break;
3384a57a6a27SRajkumar Manoharan 	case WMI_10_2_PDEV_TEMPERATURE_EVENTID:
3385a57a6a27SRajkumar Manoharan 		ath10k_wmi_event_temperature(ar, skb);
3386a57a6a27SRajkumar Manoharan 		break;
338724c88f78SMichal Kazior 	case WMI_10_2_RTT_KEEPALIVE_EVENTID:
338824c88f78SMichal Kazior 	case WMI_10_2_GPIO_INPUT_EVENTID:
338924c88f78SMichal Kazior 	case WMI_10_2_PEER_RATECODE_LIST_EVENTID:
339024c88f78SMichal Kazior 	case WMI_10_2_GENERIC_BUFFER_EVENTID:
339124c88f78SMichal Kazior 	case WMI_10_2_MCAST_BUF_RELEASE_EVENTID:
339224c88f78SMichal Kazior 	case WMI_10_2_MCAST_LIST_AGEOUT_EVENTID:
339324c88f78SMichal Kazior 	case WMI_10_2_WDS_PEER_EVENTID:
33947aa7a72aSMichal Kazior 		ath10k_dbg(ar, ATH10K_DBG_WMI,
339524c88f78SMichal Kazior 			   "received event id %d not implemented\n", id);
339624c88f78SMichal Kazior 		break;
339724c88f78SMichal Kazior 	default:
33987aa7a72aSMichal Kazior 		ath10k_warn(ar, "Unknown eventid: %d\n", id);
339924c88f78SMichal Kazior 		break;
340024c88f78SMichal Kazior 	}
340124c88f78SMichal Kazior 
340224c88f78SMichal Kazior 	dev_kfree_skb(skb);
340324c88f78SMichal Kazior }
34048a6618b0SBartosz Markowski 
3405ce42870eSBartosz Markowski static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb)
3406ce42870eSBartosz Markowski {
3407d7579d12SMichal Kazior 	int ret;
3408d7579d12SMichal Kazior 
3409d7579d12SMichal Kazior 	ret = ath10k_wmi_rx(ar, skb);
3410d7579d12SMichal Kazior 	if (ret)
3411d7579d12SMichal Kazior 		ath10k_warn(ar, "failed to process wmi rx: %d\n", ret);
341224c88f78SMichal Kazior }
3413ce42870eSBartosz Markowski 
341495bf21f9SMichal Kazior int ath10k_wmi_connect(struct ath10k *ar)
34155e3dd157SKalle Valo {
34165e3dd157SKalle Valo 	int status;
34175e3dd157SKalle Valo 	struct ath10k_htc_svc_conn_req conn_req;
34185e3dd157SKalle Valo 	struct ath10k_htc_svc_conn_resp conn_resp;
34195e3dd157SKalle Valo 
34205e3dd157SKalle Valo 	memset(&conn_req, 0, sizeof(conn_req));
34215e3dd157SKalle Valo 	memset(&conn_resp, 0, sizeof(conn_resp));
34225e3dd157SKalle Valo 
34235e3dd157SKalle Valo 	/* these fields are the same for all service endpoints */
34245e3dd157SKalle Valo 	conn_req.ep_ops.ep_tx_complete = ath10k_wmi_htc_tx_complete;
34255e3dd157SKalle Valo 	conn_req.ep_ops.ep_rx_complete = ath10k_wmi_process_rx;
3426be8b3943SMichal Kazior 	conn_req.ep_ops.ep_tx_credits = ath10k_wmi_op_ep_tx_credits;
34275e3dd157SKalle Valo 
34285e3dd157SKalle Valo 	/* connect to control service */
34295e3dd157SKalle Valo 	conn_req.service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL;
34305e3dd157SKalle Valo 
3431cd003fadSMichal Kazior 	status = ath10k_htc_connect_service(&ar->htc, &conn_req, &conn_resp);
34325e3dd157SKalle Valo 	if (status) {
34337aa7a72aSMichal Kazior 		ath10k_warn(ar, "failed to connect to WMI CONTROL service status: %d\n",
34345e3dd157SKalle Valo 			    status);
34355e3dd157SKalle Valo 		return status;
34365e3dd157SKalle Valo 	}
34375e3dd157SKalle Valo 
34385e3dd157SKalle Valo 	ar->wmi.eid = conn_resp.eid;
34395e3dd157SKalle Valo 	return 0;
34405e3dd157SKalle Valo }
34415e3dd157SKalle Valo 
3442d7579d12SMichal Kazior static struct sk_buff *
3443d7579d12SMichal Kazior ath10k_wmi_op_gen_pdev_set_rd(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g,
3444d7579d12SMichal Kazior 			      u16 ctl2g, u16 ctl5g,
3445d7579d12SMichal Kazior 			      enum wmi_dfs_region dfs_reg)
34465e3dd157SKalle Valo {
34475e3dd157SKalle Valo 	struct wmi_pdev_set_regdomain_cmd *cmd;
34485e3dd157SKalle Valo 	struct sk_buff *skb;
34495e3dd157SKalle Valo 
34507aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
34515e3dd157SKalle Valo 	if (!skb)
3452d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
34535e3dd157SKalle Valo 
34545e3dd157SKalle Valo 	cmd = (struct wmi_pdev_set_regdomain_cmd *)skb->data;
34555e3dd157SKalle Valo 	cmd->reg_domain = __cpu_to_le32(rd);
34565e3dd157SKalle Valo 	cmd->reg_domain_2G = __cpu_to_le32(rd2g);
34575e3dd157SKalle Valo 	cmd->reg_domain_5G = __cpu_to_le32(rd5g);
34585e3dd157SKalle Valo 	cmd->conformance_test_limit_2G = __cpu_to_le32(ctl2g);
34595e3dd157SKalle Valo 	cmd->conformance_test_limit_5G = __cpu_to_le32(ctl5g);
34605e3dd157SKalle Valo 
34617aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
34625e3dd157SKalle Valo 		   "wmi pdev regdomain rd %x rd2g %x rd5g %x ctl2g %x ctl5g %x\n",
34635e3dd157SKalle Valo 		   rd, rd2g, rd5g, ctl2g, ctl5g);
3464d7579d12SMichal Kazior 	return skb;
34655e3dd157SKalle Valo }
34665e3dd157SKalle Valo 
3467d7579d12SMichal Kazior static struct sk_buff *
3468d7579d12SMichal Kazior ath10k_wmi_10x_op_gen_pdev_set_rd(struct ath10k *ar, u16 rd, u16 rd2g, u16
3469d7579d12SMichal Kazior 				  rd5g, u16 ctl2g, u16 ctl5g,
3470821af6aeSMarek Puzyniak 				  enum wmi_dfs_region dfs_reg)
3471821af6aeSMarek Puzyniak {
3472821af6aeSMarek Puzyniak 	struct wmi_pdev_set_regdomain_cmd_10x *cmd;
3473821af6aeSMarek Puzyniak 	struct sk_buff *skb;
3474821af6aeSMarek Puzyniak 
34757aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
3476821af6aeSMarek Puzyniak 	if (!skb)
3477d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
3478821af6aeSMarek Puzyniak 
3479821af6aeSMarek Puzyniak 	cmd = (struct wmi_pdev_set_regdomain_cmd_10x *)skb->data;
3480821af6aeSMarek Puzyniak 	cmd->reg_domain = __cpu_to_le32(rd);
3481821af6aeSMarek Puzyniak 	cmd->reg_domain_2G = __cpu_to_le32(rd2g);
3482821af6aeSMarek Puzyniak 	cmd->reg_domain_5G = __cpu_to_le32(rd5g);
3483821af6aeSMarek Puzyniak 	cmd->conformance_test_limit_2G = __cpu_to_le32(ctl2g);
3484821af6aeSMarek Puzyniak 	cmd->conformance_test_limit_5G = __cpu_to_le32(ctl5g);
3485821af6aeSMarek Puzyniak 	cmd->dfs_domain = __cpu_to_le32(dfs_reg);
3486821af6aeSMarek Puzyniak 
34877aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
3488821af6aeSMarek Puzyniak 		   "wmi pdev regdomain rd %x rd2g %x rd5g %x ctl2g %x ctl5g %x dfs_region %x\n",
3489821af6aeSMarek Puzyniak 		   rd, rd2g, rd5g, ctl2g, ctl5g, dfs_reg);
3490d7579d12SMichal Kazior 	return skb;
3491821af6aeSMarek Puzyniak }
3492821af6aeSMarek Puzyniak 
3493d7579d12SMichal Kazior static struct sk_buff *
3494d7579d12SMichal Kazior ath10k_wmi_op_gen_pdev_suspend(struct ath10k *ar, u32 suspend_opt)
34955e3dd157SKalle Valo {
34965e3dd157SKalle Valo 	struct wmi_pdev_suspend_cmd *cmd;
34975e3dd157SKalle Valo 	struct sk_buff *skb;
34985e3dd157SKalle Valo 
34997aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
35005e3dd157SKalle Valo 	if (!skb)
3501d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
35025e3dd157SKalle Valo 
35035e3dd157SKalle Valo 	cmd = (struct wmi_pdev_suspend_cmd *)skb->data;
350400f5482bSMarek Puzyniak 	cmd->suspend_opt = __cpu_to_le32(suspend_opt);
35055e3dd157SKalle Valo 
3506d7579d12SMichal Kazior 	return skb;
35075e3dd157SKalle Valo }
35085e3dd157SKalle Valo 
3509d7579d12SMichal Kazior static struct sk_buff *
3510d7579d12SMichal Kazior ath10k_wmi_op_gen_pdev_resume(struct ath10k *ar)
35115e3dd157SKalle Valo {
35125e3dd157SKalle Valo 	struct sk_buff *skb;
35135e3dd157SKalle Valo 
35147aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, 0);
3515d7579d12SMichal Kazior 	if (!skb)
3516d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
35175e3dd157SKalle Valo 
3518d7579d12SMichal Kazior 	return skb;
35195e3dd157SKalle Valo }
35205e3dd157SKalle Valo 
3521d7579d12SMichal Kazior static struct sk_buff *
3522d7579d12SMichal Kazior ath10k_wmi_op_gen_pdev_set_param(struct ath10k *ar, u32 id, u32 value)
35235e3dd157SKalle Valo {
35245e3dd157SKalle Valo 	struct wmi_pdev_set_param_cmd *cmd;
35255e3dd157SKalle Valo 	struct sk_buff *skb;
35265e3dd157SKalle Valo 
3527226a339bSBartosz Markowski 	if (id == WMI_PDEV_PARAM_UNSUPPORTED) {
35287aa7a72aSMichal Kazior 		ath10k_warn(ar, "pdev param %d not supported by firmware\n",
35297aa7a72aSMichal Kazior 			    id);
3530d7579d12SMichal Kazior 		return ERR_PTR(-EOPNOTSUPP);
3531226a339bSBartosz Markowski 	}
3532226a339bSBartosz Markowski 
35337aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
35345e3dd157SKalle Valo 	if (!skb)
3535d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
35365e3dd157SKalle Valo 
35375e3dd157SKalle Valo 	cmd = (struct wmi_pdev_set_param_cmd *)skb->data;
35385e3dd157SKalle Valo 	cmd->param_id    = __cpu_to_le32(id);
35395e3dd157SKalle Valo 	cmd->param_value = __cpu_to_le32(value);
35405e3dd157SKalle Valo 
35417aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi pdev set param %d value %d\n",
35425e3dd157SKalle Valo 		   id, value);
3543d7579d12SMichal Kazior 	return skb;
35445e3dd157SKalle Valo }
35455e3dd157SKalle Valo 
35460226d602SMichal Kazior void ath10k_wmi_put_host_mem_chunks(struct ath10k *ar,
3547cf9fca8fSMichal Kazior 				    struct wmi_host_mem_chunks *chunks)
3548cf9fca8fSMichal Kazior {
3549cf9fca8fSMichal Kazior 	struct host_memory_chunk *chunk;
3550cf9fca8fSMichal Kazior 	int i;
3551cf9fca8fSMichal Kazior 
3552cf9fca8fSMichal Kazior 	chunks->count = __cpu_to_le32(ar->wmi.num_mem_chunks);
3553cf9fca8fSMichal Kazior 
3554cf9fca8fSMichal Kazior 	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
3555cf9fca8fSMichal Kazior 		chunk = &chunks->items[i];
3556cf9fca8fSMichal Kazior 		chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
3557cf9fca8fSMichal Kazior 		chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len);
3558cf9fca8fSMichal Kazior 		chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
3559cf9fca8fSMichal Kazior 
3560cf9fca8fSMichal Kazior 		ath10k_dbg(ar, ATH10K_DBG_WMI,
3561cf9fca8fSMichal Kazior 			   "wmi chunk %d len %d requested, addr 0x%llx\n",
3562cf9fca8fSMichal Kazior 			   i,
3563cf9fca8fSMichal Kazior 			   ar->wmi.mem_chunks[i].len,
3564cf9fca8fSMichal Kazior 			   (unsigned long long)ar->wmi.mem_chunks[i].paddr);
3565cf9fca8fSMichal Kazior 	}
3566cf9fca8fSMichal Kazior }
3567cf9fca8fSMichal Kazior 
3568d7579d12SMichal Kazior static struct sk_buff *ath10k_wmi_op_gen_init(struct ath10k *ar)
35695e3dd157SKalle Valo {
35705e3dd157SKalle Valo 	struct wmi_init_cmd *cmd;
35715e3dd157SKalle Valo 	struct sk_buff *buf;
35725e3dd157SKalle Valo 	struct wmi_resource_config config = {};
3573b3effe61SBartosz Markowski 	u32 len, val;
35745e3dd157SKalle Valo 
35755e3dd157SKalle Valo 	config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS);
3576cfd1061eSMichal Kazior 	config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS);
35775e3dd157SKalle Valo 	config.num_offload_peers = __cpu_to_le32(TARGET_NUM_OFFLOAD_PEERS);
35785e3dd157SKalle Valo 
35795e3dd157SKalle Valo 	config.num_offload_reorder_bufs =
35805e3dd157SKalle Valo 		__cpu_to_le32(TARGET_NUM_OFFLOAD_REORDER_BUFS);
35815e3dd157SKalle Valo 
35825e3dd157SKalle Valo 	config.num_peer_keys = __cpu_to_le32(TARGET_NUM_PEER_KEYS);
35835e3dd157SKalle Valo 	config.num_tids = __cpu_to_le32(TARGET_NUM_TIDS);
35845e3dd157SKalle Valo 	config.ast_skid_limit = __cpu_to_le32(TARGET_AST_SKID_LIMIT);
35855e3dd157SKalle Valo 	config.tx_chain_mask = __cpu_to_le32(TARGET_TX_CHAIN_MASK);
35865e3dd157SKalle Valo 	config.rx_chain_mask = __cpu_to_le32(TARGET_RX_CHAIN_MASK);
35875e3dd157SKalle Valo 	config.rx_timeout_pri_vo = __cpu_to_le32(TARGET_RX_TIMEOUT_LO_PRI);
35885e3dd157SKalle Valo 	config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_RX_TIMEOUT_LO_PRI);
35895e3dd157SKalle Valo 	config.rx_timeout_pri_be = __cpu_to_le32(TARGET_RX_TIMEOUT_LO_PRI);
35905e3dd157SKalle Valo 	config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_RX_TIMEOUT_HI_PRI);
35915e3dd157SKalle Valo 	config.rx_decap_mode = __cpu_to_le32(TARGET_RX_DECAP_MODE);
35925e3dd157SKalle Valo 
35935e3dd157SKalle Valo 	config.scan_max_pending_reqs =
35945e3dd157SKalle Valo 		__cpu_to_le32(TARGET_SCAN_MAX_PENDING_REQS);
35955e3dd157SKalle Valo 
35965e3dd157SKalle Valo 	config.bmiss_offload_max_vdev =
35975e3dd157SKalle Valo 		__cpu_to_le32(TARGET_BMISS_OFFLOAD_MAX_VDEV);
35985e3dd157SKalle Valo 
35995e3dd157SKalle Valo 	config.roam_offload_max_vdev =
36005e3dd157SKalle Valo 		__cpu_to_le32(TARGET_ROAM_OFFLOAD_MAX_VDEV);
36015e3dd157SKalle Valo 
36025e3dd157SKalle Valo 	config.roam_offload_max_ap_profiles =
36035e3dd157SKalle Valo 		__cpu_to_le32(TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES);
36045e3dd157SKalle Valo 
36055e3dd157SKalle Valo 	config.num_mcast_groups = __cpu_to_le32(TARGET_NUM_MCAST_GROUPS);
36065e3dd157SKalle Valo 	config.num_mcast_table_elems =
36075e3dd157SKalle Valo 		__cpu_to_le32(TARGET_NUM_MCAST_TABLE_ELEMS);
36085e3dd157SKalle Valo 
36095e3dd157SKalle Valo 	config.mcast2ucast_mode = __cpu_to_le32(TARGET_MCAST2UCAST_MODE);
36105e3dd157SKalle Valo 	config.tx_dbg_log_size = __cpu_to_le32(TARGET_TX_DBG_LOG_SIZE);
36115e3dd157SKalle Valo 	config.num_wds_entries = __cpu_to_le32(TARGET_NUM_WDS_ENTRIES);
36125e3dd157SKalle Valo 	config.dma_burst_size = __cpu_to_le32(TARGET_DMA_BURST_SIZE);
36135e3dd157SKalle Valo 	config.mac_aggr_delim = __cpu_to_le32(TARGET_MAC_AGGR_DELIM);
36145e3dd157SKalle Valo 
36155e3dd157SKalle Valo 	val = TARGET_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK;
36165e3dd157SKalle Valo 	config.rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(val);
36175e3dd157SKalle Valo 
36185e3dd157SKalle Valo 	config.vow_config = __cpu_to_le32(TARGET_VOW_CONFIG);
36195e3dd157SKalle Valo 
36205e3dd157SKalle Valo 	config.gtk_offload_max_vdev =
36215e3dd157SKalle Valo 		__cpu_to_le32(TARGET_GTK_OFFLOAD_MAX_VDEV);
36225e3dd157SKalle Valo 
36235e3dd157SKalle Valo 	config.num_msdu_desc = __cpu_to_le32(TARGET_NUM_MSDU_DESC);
36245e3dd157SKalle Valo 	config.max_frag_entries = __cpu_to_le32(TARGET_MAX_FRAG_ENTRIES);
36255e3dd157SKalle Valo 
3626b3effe61SBartosz Markowski 	len = sizeof(*cmd) +
3627b3effe61SBartosz Markowski 	      (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks);
3628b3effe61SBartosz Markowski 
36297aa7a72aSMichal Kazior 	buf = ath10k_wmi_alloc_skb(ar, len);
36305e3dd157SKalle Valo 	if (!buf)
3631d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
36325e3dd157SKalle Valo 
36335e3dd157SKalle Valo 	cmd = (struct wmi_init_cmd *)buf->data;
3634b3effe61SBartosz Markowski 
36355e3dd157SKalle Valo 	memcpy(&cmd->resource_config, &config, sizeof(config));
3636cf9fca8fSMichal Kazior 	ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
36375e3dd157SKalle Valo 
36387aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init\n");
3639d7579d12SMichal Kazior 	return buf;
36405e3dd157SKalle Valo }
36415e3dd157SKalle Valo 
3642d7579d12SMichal Kazior static struct sk_buff *ath10k_wmi_10_1_op_gen_init(struct ath10k *ar)
364312b2b9e3SBartosz Markowski {
364412b2b9e3SBartosz Markowski 	struct wmi_init_cmd_10x *cmd;
364512b2b9e3SBartosz Markowski 	struct sk_buff *buf;
364612b2b9e3SBartosz Markowski 	struct wmi_resource_config_10x config = {};
364712b2b9e3SBartosz Markowski 	u32 len, val;
364812b2b9e3SBartosz Markowski 
3649ec6a73f0SBartosz Markowski 	config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
3650ec6a73f0SBartosz Markowski 	config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS);
3651ec6a73f0SBartosz Markowski 	config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS);
3652ec6a73f0SBartosz Markowski 	config.num_tids = __cpu_to_le32(TARGET_10X_NUM_TIDS);
3653ec6a73f0SBartosz Markowski 	config.ast_skid_limit = __cpu_to_le32(TARGET_10X_AST_SKID_LIMIT);
3654ec6a73f0SBartosz Markowski 	config.tx_chain_mask = __cpu_to_le32(TARGET_10X_TX_CHAIN_MASK);
3655ec6a73f0SBartosz Markowski 	config.rx_chain_mask = __cpu_to_le32(TARGET_10X_RX_CHAIN_MASK);
3656ec6a73f0SBartosz Markowski 	config.rx_timeout_pri_vo = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
3657ec6a73f0SBartosz Markowski 	config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
3658ec6a73f0SBartosz Markowski 	config.rx_timeout_pri_be = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
3659ec6a73f0SBartosz Markowski 	config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_HI_PRI);
3660ec6a73f0SBartosz Markowski 	config.rx_decap_mode = __cpu_to_le32(TARGET_10X_RX_DECAP_MODE);
366112b2b9e3SBartosz Markowski 
366212b2b9e3SBartosz Markowski 	config.scan_max_pending_reqs =
3663ec6a73f0SBartosz Markowski 		__cpu_to_le32(TARGET_10X_SCAN_MAX_PENDING_REQS);
366412b2b9e3SBartosz Markowski 
366512b2b9e3SBartosz Markowski 	config.bmiss_offload_max_vdev =
3666ec6a73f0SBartosz Markowski 		__cpu_to_le32(TARGET_10X_BMISS_OFFLOAD_MAX_VDEV);
366712b2b9e3SBartosz Markowski 
366812b2b9e3SBartosz Markowski 	config.roam_offload_max_vdev =
3669ec6a73f0SBartosz Markowski 		__cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_VDEV);
367012b2b9e3SBartosz Markowski 
367112b2b9e3SBartosz Markowski 	config.roam_offload_max_ap_profiles =
3672ec6a73f0SBartosz Markowski 		__cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_AP_PROFILES);
367312b2b9e3SBartosz Markowski 
3674ec6a73f0SBartosz Markowski 	config.num_mcast_groups = __cpu_to_le32(TARGET_10X_NUM_MCAST_GROUPS);
367512b2b9e3SBartosz Markowski 	config.num_mcast_table_elems =
3676ec6a73f0SBartosz Markowski 		__cpu_to_le32(TARGET_10X_NUM_MCAST_TABLE_ELEMS);
367712b2b9e3SBartosz Markowski 
3678ec6a73f0SBartosz Markowski 	config.mcast2ucast_mode = __cpu_to_le32(TARGET_10X_MCAST2UCAST_MODE);
3679ec6a73f0SBartosz Markowski 	config.tx_dbg_log_size = __cpu_to_le32(TARGET_10X_TX_DBG_LOG_SIZE);
3680ec6a73f0SBartosz Markowski 	config.num_wds_entries = __cpu_to_le32(TARGET_10X_NUM_WDS_ENTRIES);
3681ec6a73f0SBartosz Markowski 	config.dma_burst_size = __cpu_to_le32(TARGET_10X_DMA_BURST_SIZE);
3682ec6a73f0SBartosz Markowski 	config.mac_aggr_delim = __cpu_to_le32(TARGET_10X_MAC_AGGR_DELIM);
368312b2b9e3SBartosz Markowski 
3684ec6a73f0SBartosz Markowski 	val = TARGET_10X_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK;
368512b2b9e3SBartosz Markowski 	config.rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(val);
368612b2b9e3SBartosz Markowski 
3687ec6a73f0SBartosz Markowski 	config.vow_config = __cpu_to_le32(TARGET_10X_VOW_CONFIG);
368812b2b9e3SBartosz Markowski 
3689ec6a73f0SBartosz Markowski 	config.num_msdu_desc = __cpu_to_le32(TARGET_10X_NUM_MSDU_DESC);
3690ec6a73f0SBartosz Markowski 	config.max_frag_entries = __cpu_to_le32(TARGET_10X_MAX_FRAG_ENTRIES);
369112b2b9e3SBartosz Markowski 
369212b2b9e3SBartosz Markowski 	len = sizeof(*cmd) +
369312b2b9e3SBartosz Markowski 	      (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks);
369412b2b9e3SBartosz Markowski 
36957aa7a72aSMichal Kazior 	buf = ath10k_wmi_alloc_skb(ar, len);
369612b2b9e3SBartosz Markowski 	if (!buf)
3697d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
369812b2b9e3SBartosz Markowski 
369912b2b9e3SBartosz Markowski 	cmd = (struct wmi_init_cmd_10x *)buf->data;
370012b2b9e3SBartosz Markowski 
370112b2b9e3SBartosz Markowski 	memcpy(&cmd->resource_config, &config, sizeof(config));
3702cf9fca8fSMichal Kazior 	ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
370312b2b9e3SBartosz Markowski 
37047aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10x\n");
3705d7579d12SMichal Kazior 	return buf;
370612b2b9e3SBartosz Markowski }
370712b2b9e3SBartosz Markowski 
3708d7579d12SMichal Kazior static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
370924c88f78SMichal Kazior {
371024c88f78SMichal Kazior 	struct wmi_init_cmd_10_2 *cmd;
371124c88f78SMichal Kazior 	struct sk_buff *buf;
371224c88f78SMichal Kazior 	struct wmi_resource_config_10x config = {};
3713b6c8e287SSujith Manoharan 	u32 len, val, features;
371424c88f78SMichal Kazior 
371524c88f78SMichal Kazior 	config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
371624c88f78SMichal Kazior 	config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS);
371724c88f78SMichal Kazior 	config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS);
371824c88f78SMichal Kazior 	config.num_tids = __cpu_to_le32(TARGET_10X_NUM_TIDS);
371924c88f78SMichal Kazior 	config.ast_skid_limit = __cpu_to_le32(TARGET_10X_AST_SKID_LIMIT);
372024c88f78SMichal Kazior 	config.tx_chain_mask = __cpu_to_le32(TARGET_10X_TX_CHAIN_MASK);
372124c88f78SMichal Kazior 	config.rx_chain_mask = __cpu_to_le32(TARGET_10X_RX_CHAIN_MASK);
372224c88f78SMichal Kazior 	config.rx_timeout_pri_vo = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
372324c88f78SMichal Kazior 	config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
372424c88f78SMichal Kazior 	config.rx_timeout_pri_be = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
372524c88f78SMichal Kazior 	config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_HI_PRI);
372624c88f78SMichal Kazior 	config.rx_decap_mode = __cpu_to_le32(TARGET_10X_RX_DECAP_MODE);
372724c88f78SMichal Kazior 
372824c88f78SMichal Kazior 	config.scan_max_pending_reqs =
372924c88f78SMichal Kazior 		__cpu_to_le32(TARGET_10X_SCAN_MAX_PENDING_REQS);
373024c88f78SMichal Kazior 
373124c88f78SMichal Kazior 	config.bmiss_offload_max_vdev =
373224c88f78SMichal Kazior 		__cpu_to_le32(TARGET_10X_BMISS_OFFLOAD_MAX_VDEV);
373324c88f78SMichal Kazior 
373424c88f78SMichal Kazior 	config.roam_offload_max_vdev =
373524c88f78SMichal Kazior 		__cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_VDEV);
373624c88f78SMichal Kazior 
373724c88f78SMichal Kazior 	config.roam_offload_max_ap_profiles =
373824c88f78SMichal Kazior 		__cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_AP_PROFILES);
373924c88f78SMichal Kazior 
374024c88f78SMichal Kazior 	config.num_mcast_groups = __cpu_to_le32(TARGET_10X_NUM_MCAST_GROUPS);
374124c88f78SMichal Kazior 	config.num_mcast_table_elems =
374224c88f78SMichal Kazior 		__cpu_to_le32(TARGET_10X_NUM_MCAST_TABLE_ELEMS);
374324c88f78SMichal Kazior 
374424c88f78SMichal Kazior 	config.mcast2ucast_mode = __cpu_to_le32(TARGET_10X_MCAST2UCAST_MODE);
374524c88f78SMichal Kazior 	config.tx_dbg_log_size = __cpu_to_le32(TARGET_10X_TX_DBG_LOG_SIZE);
374624c88f78SMichal Kazior 	config.num_wds_entries = __cpu_to_le32(TARGET_10X_NUM_WDS_ENTRIES);
3747f6603ff2SSujith Manoharan 	config.dma_burst_size = __cpu_to_le32(TARGET_10_2_DMA_BURST_SIZE);
374824c88f78SMichal Kazior 	config.mac_aggr_delim = __cpu_to_le32(TARGET_10X_MAC_AGGR_DELIM);
374924c88f78SMichal Kazior 
375024c88f78SMichal Kazior 	val = TARGET_10X_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK;
375124c88f78SMichal Kazior 	config.rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(val);
375224c88f78SMichal Kazior 
375324c88f78SMichal Kazior 	config.vow_config = __cpu_to_le32(TARGET_10X_VOW_CONFIG);
375424c88f78SMichal Kazior 
375524c88f78SMichal Kazior 	config.num_msdu_desc = __cpu_to_le32(TARGET_10X_NUM_MSDU_DESC);
375624c88f78SMichal Kazior 	config.max_frag_entries = __cpu_to_le32(TARGET_10X_MAX_FRAG_ENTRIES);
375724c88f78SMichal Kazior 
375824c88f78SMichal Kazior 	len = sizeof(*cmd) +
375924c88f78SMichal Kazior 	      (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks);
376024c88f78SMichal Kazior 
37617aa7a72aSMichal Kazior 	buf = ath10k_wmi_alloc_skb(ar, len);
376224c88f78SMichal Kazior 	if (!buf)
3763d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
376424c88f78SMichal Kazior 
376524c88f78SMichal Kazior 	cmd = (struct wmi_init_cmd_10_2 *)buf->data;
376624c88f78SMichal Kazior 
3767b6c8e287SSujith Manoharan 	features = WMI_10_2_RX_BATCH_MODE;
3768b6c8e287SSujith Manoharan 	cmd->resource_config.feature_mask = __cpu_to_le32(features);
3769b6c8e287SSujith Manoharan 
377024c88f78SMichal Kazior 	memcpy(&cmd->resource_config.common, &config, sizeof(config));
3771cf9fca8fSMichal Kazior 	ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
377224c88f78SMichal Kazior 
37737aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10.2\n");
3774d7579d12SMichal Kazior 	return buf;
377512b2b9e3SBartosz Markowski }
377612b2b9e3SBartosz Markowski 
37770226d602SMichal Kazior int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg)
37785e3dd157SKalle Valo {
3779a6aa5da3SMichal Kazior 	if (arg->ie_len && !arg->ie)
37805e3dd157SKalle Valo 		return -EINVAL;
3781a6aa5da3SMichal Kazior 	if (arg->n_channels && !arg->channels)
3782a6aa5da3SMichal Kazior 		return -EINVAL;
3783a6aa5da3SMichal Kazior 	if (arg->n_ssids && !arg->ssids)
3784a6aa5da3SMichal Kazior 		return -EINVAL;
3785a6aa5da3SMichal Kazior 	if (arg->n_bssids && !arg->bssids)
3786a6aa5da3SMichal Kazior 		return -EINVAL;
3787a6aa5da3SMichal Kazior 
37885e3dd157SKalle Valo 	if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN)
37895e3dd157SKalle Valo 		return -EINVAL;
3790a6aa5da3SMichal Kazior 	if (arg->n_channels > ARRAY_SIZE(arg->channels))
3791a6aa5da3SMichal Kazior 		return -EINVAL;
3792a6aa5da3SMichal Kazior 	if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID)
3793a6aa5da3SMichal Kazior 		return -EINVAL;
3794a6aa5da3SMichal Kazior 	if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID)
3795a6aa5da3SMichal Kazior 		return -EINVAL;
37965e3dd157SKalle Valo 
3797a6aa5da3SMichal Kazior 	return 0;
3798a6aa5da3SMichal Kazior }
3799a6aa5da3SMichal Kazior 
3800a6aa5da3SMichal Kazior static size_t
3801a6aa5da3SMichal Kazior ath10k_wmi_start_scan_tlvs_len(const struct wmi_start_scan_arg *arg)
3802a6aa5da3SMichal Kazior {
3803a6aa5da3SMichal Kazior 	int len = 0;
3804a6aa5da3SMichal Kazior 
3805a6aa5da3SMichal Kazior 	if (arg->ie_len) {
38065e3dd157SKalle Valo 		len += sizeof(struct wmi_ie_data);
38075e3dd157SKalle Valo 		len += roundup(arg->ie_len, 4);
38085e3dd157SKalle Valo 	}
38095e3dd157SKalle Valo 
38105e3dd157SKalle Valo 	if (arg->n_channels) {
38115e3dd157SKalle Valo 		len += sizeof(struct wmi_chan_list);
38125e3dd157SKalle Valo 		len += sizeof(__le32) * arg->n_channels;
38135e3dd157SKalle Valo 	}
38145e3dd157SKalle Valo 
38155e3dd157SKalle Valo 	if (arg->n_ssids) {
38165e3dd157SKalle Valo 		len += sizeof(struct wmi_ssid_list);
38175e3dd157SKalle Valo 		len += sizeof(struct wmi_ssid) * arg->n_ssids;
38185e3dd157SKalle Valo 	}
38195e3dd157SKalle Valo 
38205e3dd157SKalle Valo 	if (arg->n_bssids) {
38215e3dd157SKalle Valo 		len += sizeof(struct wmi_bssid_list);
38225e3dd157SKalle Valo 		len += sizeof(struct wmi_mac_addr) * arg->n_bssids;
38235e3dd157SKalle Valo 	}
38245e3dd157SKalle Valo 
38255e3dd157SKalle Valo 	return len;
38265e3dd157SKalle Valo }
38275e3dd157SKalle Valo 
38280226d602SMichal Kazior void ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn,
38295e3dd157SKalle Valo 				      const struct wmi_start_scan_arg *arg)
38305e3dd157SKalle Valo {
38315e3dd157SKalle Valo 	u32 scan_id;
38325e3dd157SKalle Valo 	u32 scan_req_id;
38335e3dd157SKalle Valo 
38345e3dd157SKalle Valo 	scan_id  = WMI_HOST_SCAN_REQ_ID_PREFIX;
38355e3dd157SKalle Valo 	scan_id |= arg->scan_id;
38365e3dd157SKalle Valo 
38375e3dd157SKalle Valo 	scan_req_id  = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX;
38385e3dd157SKalle Valo 	scan_req_id |= arg->scan_req_id;
38395e3dd157SKalle Valo 
3840a6aa5da3SMichal Kazior 	cmn->scan_id            = __cpu_to_le32(scan_id);
3841a6aa5da3SMichal Kazior 	cmn->scan_req_id        = __cpu_to_le32(scan_req_id);
3842a6aa5da3SMichal Kazior 	cmn->vdev_id            = __cpu_to_le32(arg->vdev_id);
3843a6aa5da3SMichal Kazior 	cmn->scan_priority      = __cpu_to_le32(arg->scan_priority);
3844a6aa5da3SMichal Kazior 	cmn->notify_scan_events = __cpu_to_le32(arg->notify_scan_events);
3845a6aa5da3SMichal Kazior 	cmn->dwell_time_active  = __cpu_to_le32(arg->dwell_time_active);
3846a6aa5da3SMichal Kazior 	cmn->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive);
3847a6aa5da3SMichal Kazior 	cmn->min_rest_time      = __cpu_to_le32(arg->min_rest_time);
3848a6aa5da3SMichal Kazior 	cmn->max_rest_time      = __cpu_to_le32(arg->max_rest_time);
3849a6aa5da3SMichal Kazior 	cmn->repeat_probe_time  = __cpu_to_le32(arg->repeat_probe_time);
3850a6aa5da3SMichal Kazior 	cmn->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time);
3851a6aa5da3SMichal Kazior 	cmn->idle_time          = __cpu_to_le32(arg->idle_time);
3852a6aa5da3SMichal Kazior 	cmn->max_scan_time      = __cpu_to_le32(arg->max_scan_time);
3853a6aa5da3SMichal Kazior 	cmn->probe_delay        = __cpu_to_le32(arg->probe_delay);
3854a6aa5da3SMichal Kazior 	cmn->scan_ctrl_flags    = __cpu_to_le32(arg->scan_ctrl_flags);
3855a6aa5da3SMichal Kazior }
38565e3dd157SKalle Valo 
3857a6aa5da3SMichal Kazior static void
3858a6aa5da3SMichal Kazior ath10k_wmi_put_start_scan_tlvs(struct wmi_start_scan_tlvs *tlvs,
3859a6aa5da3SMichal Kazior 			       const struct wmi_start_scan_arg *arg)
3860a6aa5da3SMichal Kazior {
3861a6aa5da3SMichal Kazior 	struct wmi_ie_data *ie;
3862a6aa5da3SMichal Kazior 	struct wmi_chan_list *channels;
3863a6aa5da3SMichal Kazior 	struct wmi_ssid_list *ssids;
3864a6aa5da3SMichal Kazior 	struct wmi_bssid_list *bssids;
3865a6aa5da3SMichal Kazior 	void *ptr = tlvs->tlvs;
3866a6aa5da3SMichal Kazior 	int i;
38675e3dd157SKalle Valo 
38685e3dd157SKalle Valo 	if (arg->n_channels) {
3869a6aa5da3SMichal Kazior 		channels = ptr;
38705e3dd157SKalle Valo 		channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG);
38715e3dd157SKalle Valo 		channels->num_chan = __cpu_to_le32(arg->n_channels);
38725e3dd157SKalle Valo 
38735e3dd157SKalle Valo 		for (i = 0; i < arg->n_channels; i++)
387424c88f78SMichal Kazior 			channels->channel_list[i].freq =
387524c88f78SMichal Kazior 				__cpu_to_le16(arg->channels[i]);
38765e3dd157SKalle Valo 
3877a6aa5da3SMichal Kazior 		ptr += sizeof(*channels);
3878a6aa5da3SMichal Kazior 		ptr += sizeof(__le32) * arg->n_channels;
38795e3dd157SKalle Valo 	}
38805e3dd157SKalle Valo 
38815e3dd157SKalle Valo 	if (arg->n_ssids) {
3882a6aa5da3SMichal Kazior 		ssids = ptr;
38835e3dd157SKalle Valo 		ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG);
38845e3dd157SKalle Valo 		ssids->num_ssids = __cpu_to_le32(arg->n_ssids);
38855e3dd157SKalle Valo 
38865e3dd157SKalle Valo 		for (i = 0; i < arg->n_ssids; i++) {
38875e3dd157SKalle Valo 			ssids->ssids[i].ssid_len =
38885e3dd157SKalle Valo 				__cpu_to_le32(arg->ssids[i].len);
38895e3dd157SKalle Valo 			memcpy(&ssids->ssids[i].ssid,
38905e3dd157SKalle Valo 			       arg->ssids[i].ssid,
38915e3dd157SKalle Valo 			       arg->ssids[i].len);
38925e3dd157SKalle Valo 		}
38935e3dd157SKalle Valo 
3894a6aa5da3SMichal Kazior 		ptr += sizeof(*ssids);
3895a6aa5da3SMichal Kazior 		ptr += sizeof(struct wmi_ssid) * arg->n_ssids;
38965e3dd157SKalle Valo 	}
38975e3dd157SKalle Valo 
38985e3dd157SKalle Valo 	if (arg->n_bssids) {
3899a6aa5da3SMichal Kazior 		bssids = ptr;
39005e3dd157SKalle Valo 		bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG);
39015e3dd157SKalle Valo 		bssids->num_bssid = __cpu_to_le32(arg->n_bssids);
39025e3dd157SKalle Valo 
39035e3dd157SKalle Valo 		for (i = 0; i < arg->n_bssids; i++)
39045e3dd157SKalle Valo 			memcpy(&bssids->bssid_list[i],
39055e3dd157SKalle Valo 			       arg->bssids[i].bssid,
39065e3dd157SKalle Valo 			       ETH_ALEN);
39075e3dd157SKalle Valo 
3908a6aa5da3SMichal Kazior 		ptr += sizeof(*bssids);
3909a6aa5da3SMichal Kazior 		ptr += sizeof(struct wmi_mac_addr) * arg->n_bssids;
39105e3dd157SKalle Valo 	}
39115e3dd157SKalle Valo 
39125e3dd157SKalle Valo 	if (arg->ie_len) {
3913a6aa5da3SMichal Kazior 		ie = ptr;
39145e3dd157SKalle Valo 		ie->tag = __cpu_to_le32(WMI_IE_TAG);
39155e3dd157SKalle Valo 		ie->ie_len = __cpu_to_le32(arg->ie_len);
39165e3dd157SKalle Valo 		memcpy(ie->ie_data, arg->ie, arg->ie_len);
39175e3dd157SKalle Valo 
3918a6aa5da3SMichal Kazior 		ptr += sizeof(*ie);
3919a6aa5da3SMichal Kazior 		ptr += roundup(arg->ie_len, 4);
3920a6aa5da3SMichal Kazior 	}
39215e3dd157SKalle Valo }
39225e3dd157SKalle Valo 
3923d7579d12SMichal Kazior static struct sk_buff *
3924d7579d12SMichal Kazior ath10k_wmi_op_gen_start_scan(struct ath10k *ar,
3925a6aa5da3SMichal Kazior 			     const struct wmi_start_scan_arg *arg)
3926a6aa5da3SMichal Kazior {
3927d7579d12SMichal Kazior 	struct wmi_start_scan_cmd *cmd;
3928a6aa5da3SMichal Kazior 	struct sk_buff *skb;
3929a6aa5da3SMichal Kazior 	size_t len;
3930a6aa5da3SMichal Kazior 	int ret;
3931a6aa5da3SMichal Kazior 
3932a6aa5da3SMichal Kazior 	ret = ath10k_wmi_start_scan_verify(arg);
3933a6aa5da3SMichal Kazior 	if (ret)
3934d7579d12SMichal Kazior 		return ERR_PTR(ret);
3935a6aa5da3SMichal Kazior 
3936d7579d12SMichal Kazior 	len = sizeof(*cmd) + ath10k_wmi_start_scan_tlvs_len(arg);
3937a6aa5da3SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
3938a6aa5da3SMichal Kazior 	if (!skb)
3939d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
3940a6aa5da3SMichal Kazior 
3941a6aa5da3SMichal Kazior 	cmd = (struct wmi_start_scan_cmd *)skb->data;
3942a6aa5da3SMichal Kazior 
3943a6aa5da3SMichal Kazior 	ath10k_wmi_put_start_scan_common(&cmd->common, arg);
3944a6aa5da3SMichal Kazior 	ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg);
3945d7579d12SMichal Kazior 
3946d7579d12SMichal Kazior 	cmd->burst_duration_ms = __cpu_to_le32(0);
39475e3dd157SKalle Valo 
39487aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi start scan\n");
3949d7579d12SMichal Kazior 	return skb;
3950d7579d12SMichal Kazior }
3951d7579d12SMichal Kazior 
3952d7579d12SMichal Kazior static struct sk_buff *
3953d7579d12SMichal Kazior ath10k_wmi_10x_op_gen_start_scan(struct ath10k *ar,
3954d7579d12SMichal Kazior 				 const struct wmi_start_scan_arg *arg)
3955d7579d12SMichal Kazior {
3956d7579d12SMichal Kazior 	struct wmi_10x_start_scan_cmd *cmd;
3957d7579d12SMichal Kazior 	struct sk_buff *skb;
3958d7579d12SMichal Kazior 	size_t len;
3959d7579d12SMichal Kazior 	int ret;
3960d7579d12SMichal Kazior 
3961d7579d12SMichal Kazior 	ret = ath10k_wmi_start_scan_verify(arg);
3962d7579d12SMichal Kazior 	if (ret)
3963d7579d12SMichal Kazior 		return ERR_PTR(ret);
3964d7579d12SMichal Kazior 
3965d7579d12SMichal Kazior 	len = sizeof(*cmd) + ath10k_wmi_start_scan_tlvs_len(arg);
3966d7579d12SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
3967d7579d12SMichal Kazior 	if (!skb)
3968d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
3969d7579d12SMichal Kazior 
3970d7579d12SMichal Kazior 	cmd = (struct wmi_10x_start_scan_cmd *)skb->data;
3971d7579d12SMichal Kazior 
3972d7579d12SMichal Kazior 	ath10k_wmi_put_start_scan_common(&cmd->common, arg);
3973d7579d12SMichal Kazior 	ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg);
3974d7579d12SMichal Kazior 
3975d7579d12SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi 10x start scan\n");
3976d7579d12SMichal Kazior 	return skb;
39775e3dd157SKalle Valo }
39785e3dd157SKalle Valo 
39795e3dd157SKalle Valo void ath10k_wmi_start_scan_init(struct ath10k *ar,
39805e3dd157SKalle Valo 				struct wmi_start_scan_arg *arg)
39815e3dd157SKalle Valo {
39825e3dd157SKalle Valo 	/* setup commonly used values */
39835e3dd157SKalle Valo 	arg->scan_req_id = 1;
39845e3dd157SKalle Valo 	arg->scan_priority = WMI_SCAN_PRIORITY_LOW;
39855e3dd157SKalle Valo 	arg->dwell_time_active = 50;
39865e3dd157SKalle Valo 	arg->dwell_time_passive = 150;
39875e3dd157SKalle Valo 	arg->min_rest_time = 50;
39885e3dd157SKalle Valo 	arg->max_rest_time = 500;
39895e3dd157SKalle Valo 	arg->repeat_probe_time = 0;
39905e3dd157SKalle Valo 	arg->probe_spacing_time = 0;
39915e3dd157SKalle Valo 	arg->idle_time = 0;
3992c322892fSBartosz Markowski 	arg->max_scan_time = 20000;
39935e3dd157SKalle Valo 	arg->probe_delay = 5;
39945e3dd157SKalle Valo 	arg->notify_scan_events = WMI_SCAN_EVENT_STARTED
39955e3dd157SKalle Valo 		| WMI_SCAN_EVENT_COMPLETED
39965e3dd157SKalle Valo 		| WMI_SCAN_EVENT_BSS_CHANNEL
39975e3dd157SKalle Valo 		| WMI_SCAN_EVENT_FOREIGN_CHANNEL
39985e3dd157SKalle Valo 		| WMI_SCAN_EVENT_DEQUEUED;
39995e3dd157SKalle Valo 	arg->scan_ctrl_flags |= WMI_SCAN_ADD_OFDM_RATES;
40005e3dd157SKalle Valo 	arg->scan_ctrl_flags |= WMI_SCAN_CHAN_STAT_EVENT;
40015e3dd157SKalle Valo 	arg->n_bssids = 1;
40025e3dd157SKalle Valo 	arg->bssids[0].bssid = "\xFF\xFF\xFF\xFF\xFF\xFF";
40035e3dd157SKalle Valo }
40045e3dd157SKalle Valo 
4005d7579d12SMichal Kazior static struct sk_buff *
4006d7579d12SMichal Kazior ath10k_wmi_op_gen_stop_scan(struct ath10k *ar,
4007d7579d12SMichal Kazior 			    const struct wmi_stop_scan_arg *arg)
40085e3dd157SKalle Valo {
40095e3dd157SKalle Valo 	struct wmi_stop_scan_cmd *cmd;
40105e3dd157SKalle Valo 	struct sk_buff *skb;
40115e3dd157SKalle Valo 	u32 scan_id;
40125e3dd157SKalle Valo 	u32 req_id;
40135e3dd157SKalle Valo 
40145e3dd157SKalle Valo 	if (arg->req_id > 0xFFF)
4015d7579d12SMichal Kazior 		return ERR_PTR(-EINVAL);
40165e3dd157SKalle Valo 	if (arg->req_type == WMI_SCAN_STOP_ONE && arg->u.scan_id > 0xFFF)
4017d7579d12SMichal Kazior 		return ERR_PTR(-EINVAL);
40185e3dd157SKalle Valo 
40197aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
40205e3dd157SKalle Valo 	if (!skb)
4021d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
40225e3dd157SKalle Valo 
40235e3dd157SKalle Valo 	scan_id = arg->u.scan_id;
40245e3dd157SKalle Valo 	scan_id |= WMI_HOST_SCAN_REQ_ID_PREFIX;
40255e3dd157SKalle Valo 
40265e3dd157SKalle Valo 	req_id = arg->req_id;
40275e3dd157SKalle Valo 	req_id |= WMI_HOST_SCAN_REQUESTOR_ID_PREFIX;
40285e3dd157SKalle Valo 
40295e3dd157SKalle Valo 	cmd = (struct wmi_stop_scan_cmd *)skb->data;
40305e3dd157SKalle Valo 	cmd->req_type    = __cpu_to_le32(arg->req_type);
40315e3dd157SKalle Valo 	cmd->vdev_id     = __cpu_to_le32(arg->u.vdev_id);
40325e3dd157SKalle Valo 	cmd->scan_id     = __cpu_to_le32(scan_id);
40335e3dd157SKalle Valo 	cmd->scan_req_id = __cpu_to_le32(req_id);
40345e3dd157SKalle Valo 
40357aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
40365e3dd157SKalle Valo 		   "wmi stop scan reqid %d req_type %d vdev/scan_id %d\n",
40375e3dd157SKalle Valo 		   arg->req_id, arg->req_type, arg->u.scan_id);
4038d7579d12SMichal Kazior 	return skb;
40395e3dd157SKalle Valo }
40405e3dd157SKalle Valo 
4041d7579d12SMichal Kazior static struct sk_buff *
4042d7579d12SMichal Kazior ath10k_wmi_op_gen_vdev_create(struct ath10k *ar, u32 vdev_id,
40435e3dd157SKalle Valo 			      enum wmi_vdev_type type,
40445e3dd157SKalle Valo 			      enum wmi_vdev_subtype subtype,
40455e3dd157SKalle Valo 			      const u8 macaddr[ETH_ALEN])
40465e3dd157SKalle Valo {
40475e3dd157SKalle Valo 	struct wmi_vdev_create_cmd *cmd;
40485e3dd157SKalle Valo 	struct sk_buff *skb;
40495e3dd157SKalle Valo 
40507aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
40515e3dd157SKalle Valo 	if (!skb)
4052d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
40535e3dd157SKalle Valo 
40545e3dd157SKalle Valo 	cmd = (struct wmi_vdev_create_cmd *)skb->data;
40555e3dd157SKalle Valo 	cmd->vdev_id      = __cpu_to_le32(vdev_id);
40565e3dd157SKalle Valo 	cmd->vdev_type    = __cpu_to_le32(type);
40575e3dd157SKalle Valo 	cmd->vdev_subtype = __cpu_to_le32(subtype);
4058b25f32cbSKalle Valo 	ether_addr_copy(cmd->vdev_macaddr.addr, macaddr);
40595e3dd157SKalle Valo 
40607aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
40615e3dd157SKalle Valo 		   "WMI vdev create: id %d type %d subtype %d macaddr %pM\n",
40625e3dd157SKalle Valo 		   vdev_id, type, subtype, macaddr);
4063d7579d12SMichal Kazior 	return skb;
40645e3dd157SKalle Valo }
40655e3dd157SKalle Valo 
4066d7579d12SMichal Kazior static struct sk_buff *
4067d7579d12SMichal Kazior ath10k_wmi_op_gen_vdev_delete(struct ath10k *ar, u32 vdev_id)
40685e3dd157SKalle Valo {
40695e3dd157SKalle Valo 	struct wmi_vdev_delete_cmd *cmd;
40705e3dd157SKalle Valo 	struct sk_buff *skb;
40715e3dd157SKalle Valo 
40727aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
40735e3dd157SKalle Valo 	if (!skb)
4074d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
40755e3dd157SKalle Valo 
40765e3dd157SKalle Valo 	cmd = (struct wmi_vdev_delete_cmd *)skb->data;
40775e3dd157SKalle Valo 	cmd->vdev_id = __cpu_to_le32(vdev_id);
40785e3dd157SKalle Valo 
40797aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
40805e3dd157SKalle Valo 		   "WMI vdev delete id %d\n", vdev_id);
4081d7579d12SMichal Kazior 	return skb;
40825e3dd157SKalle Valo }
40835e3dd157SKalle Valo 
4084d7579d12SMichal Kazior static struct sk_buff *
4085d7579d12SMichal Kazior ath10k_wmi_op_gen_vdev_start(struct ath10k *ar,
40865e3dd157SKalle Valo 			     const struct wmi_vdev_start_request_arg *arg,
4087d7579d12SMichal Kazior 			     bool restart)
40885e3dd157SKalle Valo {
40895e3dd157SKalle Valo 	struct wmi_vdev_start_request_cmd *cmd;
40905e3dd157SKalle Valo 	struct sk_buff *skb;
40915e3dd157SKalle Valo 	const char *cmdname;
40925e3dd157SKalle Valo 	u32 flags = 0;
40935e3dd157SKalle Valo 
40945e3dd157SKalle Valo 	if (WARN_ON(arg->ssid && arg->ssid_len == 0))
4095d7579d12SMichal Kazior 		return ERR_PTR(-EINVAL);
40965e3dd157SKalle Valo 	if (WARN_ON(arg->hidden_ssid && !arg->ssid))
4097d7579d12SMichal Kazior 		return ERR_PTR(-EINVAL);
40985e3dd157SKalle Valo 	if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid)))
4099d7579d12SMichal Kazior 		return ERR_PTR(-EINVAL);
41005e3dd157SKalle Valo 
4101d7579d12SMichal Kazior 	if (restart)
41025e3dd157SKalle Valo 		cmdname = "restart";
41035e3dd157SKalle Valo 	else
4104d7579d12SMichal Kazior 		cmdname = "start";
41055e3dd157SKalle Valo 
41067aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
41075e3dd157SKalle Valo 	if (!skb)
4108d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
41095e3dd157SKalle Valo 
41105e3dd157SKalle Valo 	if (arg->hidden_ssid)
41115e3dd157SKalle Valo 		flags |= WMI_VDEV_START_HIDDEN_SSID;
41125e3dd157SKalle Valo 	if (arg->pmf_enabled)
41135e3dd157SKalle Valo 		flags |= WMI_VDEV_START_PMF_ENABLED;
41145e3dd157SKalle Valo 
41155e3dd157SKalle Valo 	cmd = (struct wmi_vdev_start_request_cmd *)skb->data;
41165e3dd157SKalle Valo 	cmd->vdev_id         = __cpu_to_le32(arg->vdev_id);
41175e3dd157SKalle Valo 	cmd->disable_hw_ack  = __cpu_to_le32(arg->disable_hw_ack);
41185e3dd157SKalle Valo 	cmd->beacon_interval = __cpu_to_le32(arg->bcn_intval);
41195e3dd157SKalle Valo 	cmd->dtim_period     = __cpu_to_le32(arg->dtim_period);
41205e3dd157SKalle Valo 	cmd->flags           = __cpu_to_le32(flags);
41215e3dd157SKalle Valo 	cmd->bcn_tx_rate     = __cpu_to_le32(arg->bcn_tx_rate);
41225e3dd157SKalle Valo 	cmd->bcn_tx_power    = __cpu_to_le32(arg->bcn_tx_power);
41235e3dd157SKalle Valo 
41245e3dd157SKalle Valo 	if (arg->ssid) {
41255e3dd157SKalle Valo 		cmd->ssid.ssid_len = __cpu_to_le32(arg->ssid_len);
41265e3dd157SKalle Valo 		memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len);
41275e3dd157SKalle Valo 	}
41285e3dd157SKalle Valo 
41292d66721cSMichal Kazior 	ath10k_wmi_put_wmi_channel(&cmd->chan, &arg->channel);
41305e3dd157SKalle Valo 
41317aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
41328cc7f26cSKalle Valo 		   "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, ch_flags: 0x%0X, max_power: %d\n",
41338cc7f26cSKalle Valo 		   cmdname, arg->vdev_id,
4134e8a50f8bSMarek Puzyniak 		   flags, arg->channel.freq, arg->channel.mode,
4135e8a50f8bSMarek Puzyniak 		   cmd->chan.flags, arg->channel.max_power);
41365e3dd157SKalle Valo 
4137d7579d12SMichal Kazior 	return skb;
41385e3dd157SKalle Valo }
41395e3dd157SKalle Valo 
4140d7579d12SMichal Kazior static struct sk_buff *
4141d7579d12SMichal Kazior ath10k_wmi_op_gen_vdev_stop(struct ath10k *ar, u32 vdev_id)
41425e3dd157SKalle Valo {
41435e3dd157SKalle Valo 	struct wmi_vdev_stop_cmd *cmd;
41445e3dd157SKalle Valo 	struct sk_buff *skb;
41455e3dd157SKalle Valo 
41467aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
41475e3dd157SKalle Valo 	if (!skb)
4148d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
41495e3dd157SKalle Valo 
41505e3dd157SKalle Valo 	cmd = (struct wmi_vdev_stop_cmd *)skb->data;
41515e3dd157SKalle Valo 	cmd->vdev_id = __cpu_to_le32(vdev_id);
41525e3dd157SKalle Valo 
41537aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi vdev stop id 0x%x\n", vdev_id);
4154d7579d12SMichal Kazior 	return skb;
41555e3dd157SKalle Valo }
41565e3dd157SKalle Valo 
4157d7579d12SMichal Kazior static struct sk_buff *
4158d7579d12SMichal Kazior ath10k_wmi_op_gen_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid,
4159d7579d12SMichal Kazior 			  const u8 *bssid)
41605e3dd157SKalle Valo {
41615e3dd157SKalle Valo 	struct wmi_vdev_up_cmd *cmd;
41625e3dd157SKalle Valo 	struct sk_buff *skb;
41635e3dd157SKalle Valo 
41647aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
41655e3dd157SKalle Valo 	if (!skb)
4166d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
41675e3dd157SKalle Valo 
41685e3dd157SKalle Valo 	cmd = (struct wmi_vdev_up_cmd *)skb->data;
41695e3dd157SKalle Valo 	cmd->vdev_id       = __cpu_to_le32(vdev_id);
41705e3dd157SKalle Valo 	cmd->vdev_assoc_id = __cpu_to_le32(aid);
4171b25f32cbSKalle Valo 	ether_addr_copy(cmd->vdev_bssid.addr, bssid);
41725e3dd157SKalle Valo 
41737aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
41745e3dd157SKalle Valo 		   "wmi mgmt vdev up id 0x%x assoc id %d bssid %pM\n",
41755e3dd157SKalle Valo 		   vdev_id, aid, bssid);
4176d7579d12SMichal Kazior 	return skb;
41775e3dd157SKalle Valo }
41785e3dd157SKalle Valo 
4179d7579d12SMichal Kazior static struct sk_buff *
4180d7579d12SMichal Kazior ath10k_wmi_op_gen_vdev_down(struct ath10k *ar, u32 vdev_id)
41815e3dd157SKalle Valo {
41825e3dd157SKalle Valo 	struct wmi_vdev_down_cmd *cmd;
41835e3dd157SKalle Valo 	struct sk_buff *skb;
41845e3dd157SKalle Valo 
41857aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
41865e3dd157SKalle Valo 	if (!skb)
4187d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
41885e3dd157SKalle Valo 
41895e3dd157SKalle Valo 	cmd = (struct wmi_vdev_down_cmd *)skb->data;
41905e3dd157SKalle Valo 	cmd->vdev_id = __cpu_to_le32(vdev_id);
41915e3dd157SKalle Valo 
41927aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
41935e3dd157SKalle Valo 		   "wmi mgmt vdev down id 0x%x\n", vdev_id);
4194d7579d12SMichal Kazior 	return skb;
41955e3dd157SKalle Valo }
41965e3dd157SKalle Valo 
4197d7579d12SMichal Kazior static struct sk_buff *
4198d7579d12SMichal Kazior ath10k_wmi_op_gen_vdev_set_param(struct ath10k *ar, u32 vdev_id,
41996d1506e7SBartosz Markowski 				 u32 param_id, u32 param_value)
42005e3dd157SKalle Valo {
42015e3dd157SKalle Valo 	struct wmi_vdev_set_param_cmd *cmd;
42025e3dd157SKalle Valo 	struct sk_buff *skb;
42035e3dd157SKalle Valo 
42046d1506e7SBartosz Markowski 	if (param_id == WMI_VDEV_PARAM_UNSUPPORTED) {
42057aa7a72aSMichal Kazior 		ath10k_dbg(ar, ATH10K_DBG_WMI,
42066d1506e7SBartosz Markowski 			   "vdev param %d not supported by firmware\n",
42076d1506e7SBartosz Markowski 			    param_id);
4208d7579d12SMichal Kazior 		return ERR_PTR(-EOPNOTSUPP);
42096d1506e7SBartosz Markowski 	}
42106d1506e7SBartosz Markowski 
42117aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
42125e3dd157SKalle Valo 	if (!skb)
4213d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
42145e3dd157SKalle Valo 
42155e3dd157SKalle Valo 	cmd = (struct wmi_vdev_set_param_cmd *)skb->data;
42165e3dd157SKalle Valo 	cmd->vdev_id     = __cpu_to_le32(vdev_id);
42175e3dd157SKalle Valo 	cmd->param_id    = __cpu_to_le32(param_id);
42185e3dd157SKalle Valo 	cmd->param_value = __cpu_to_le32(param_value);
42195e3dd157SKalle Valo 
42207aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
42215e3dd157SKalle Valo 		   "wmi vdev id 0x%x set param %d value %d\n",
42225e3dd157SKalle Valo 		   vdev_id, param_id, param_value);
4223d7579d12SMichal Kazior 	return skb;
42245e3dd157SKalle Valo }
42255e3dd157SKalle Valo 
4226d7579d12SMichal Kazior static struct sk_buff *
4227d7579d12SMichal Kazior ath10k_wmi_op_gen_vdev_install_key(struct ath10k *ar,
42285e3dd157SKalle Valo 				   const struct wmi_vdev_install_key_arg *arg)
42295e3dd157SKalle Valo {
42305e3dd157SKalle Valo 	struct wmi_vdev_install_key_cmd *cmd;
42315e3dd157SKalle Valo 	struct sk_buff *skb;
42325e3dd157SKalle Valo 
42335e3dd157SKalle Valo 	if (arg->key_cipher == WMI_CIPHER_NONE && arg->key_data != NULL)
4234d7579d12SMichal Kazior 		return ERR_PTR(-EINVAL);
42355e3dd157SKalle Valo 	if (arg->key_cipher != WMI_CIPHER_NONE && arg->key_data == NULL)
4236d7579d12SMichal Kazior 		return ERR_PTR(-EINVAL);
42375e3dd157SKalle Valo 
42387aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + arg->key_len);
42395e3dd157SKalle Valo 	if (!skb)
4240d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
42415e3dd157SKalle Valo 
42425e3dd157SKalle Valo 	cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
42435e3dd157SKalle Valo 	cmd->vdev_id       = __cpu_to_le32(arg->vdev_id);
42445e3dd157SKalle Valo 	cmd->key_idx       = __cpu_to_le32(arg->key_idx);
42455e3dd157SKalle Valo 	cmd->key_flags     = __cpu_to_le32(arg->key_flags);
42465e3dd157SKalle Valo 	cmd->key_cipher    = __cpu_to_le32(arg->key_cipher);
42475e3dd157SKalle Valo 	cmd->key_len       = __cpu_to_le32(arg->key_len);
42485e3dd157SKalle Valo 	cmd->key_txmic_len = __cpu_to_le32(arg->key_txmic_len);
42495e3dd157SKalle Valo 	cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len);
42505e3dd157SKalle Valo 
42515e3dd157SKalle Valo 	if (arg->macaddr)
4252b25f32cbSKalle Valo 		ether_addr_copy(cmd->peer_macaddr.addr, arg->macaddr);
42535e3dd157SKalle Valo 	if (arg->key_data)
42545e3dd157SKalle Valo 		memcpy(cmd->key_data, arg->key_data, arg->key_len);
42555e3dd157SKalle Valo 
42567aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
4257e0c508abSMichal Kazior 		   "wmi vdev install key idx %d cipher %d len %d\n",
4258e0c508abSMichal Kazior 		   arg->key_idx, arg->key_cipher, arg->key_len);
4259d7579d12SMichal Kazior 	return skb;
42605e3dd157SKalle Valo }
42615e3dd157SKalle Valo 
4262d7579d12SMichal Kazior static struct sk_buff *
4263d7579d12SMichal Kazior ath10k_wmi_op_gen_vdev_spectral_conf(struct ath10k *ar,
4264855aed12SSimon Wunderlich 				     const struct wmi_vdev_spectral_conf_arg *arg)
4265855aed12SSimon Wunderlich {
4266855aed12SSimon Wunderlich 	struct wmi_vdev_spectral_conf_cmd *cmd;
4267855aed12SSimon Wunderlich 	struct sk_buff *skb;
4268855aed12SSimon Wunderlich 
42697aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
4270855aed12SSimon Wunderlich 	if (!skb)
4271d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
4272855aed12SSimon Wunderlich 
4273855aed12SSimon Wunderlich 	cmd = (struct wmi_vdev_spectral_conf_cmd *)skb->data;
4274855aed12SSimon Wunderlich 	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
4275855aed12SSimon Wunderlich 	cmd->scan_count = __cpu_to_le32(arg->scan_count);
4276855aed12SSimon Wunderlich 	cmd->scan_period = __cpu_to_le32(arg->scan_period);
4277855aed12SSimon Wunderlich 	cmd->scan_priority = __cpu_to_le32(arg->scan_priority);
4278855aed12SSimon Wunderlich 	cmd->scan_fft_size = __cpu_to_le32(arg->scan_fft_size);
4279855aed12SSimon Wunderlich 	cmd->scan_gc_ena = __cpu_to_le32(arg->scan_gc_ena);
4280855aed12SSimon Wunderlich 	cmd->scan_restart_ena = __cpu_to_le32(arg->scan_restart_ena);
4281855aed12SSimon Wunderlich 	cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref);
4282855aed12SSimon Wunderlich 	cmd->scan_init_delay = __cpu_to_le32(arg->scan_init_delay);
4283855aed12SSimon Wunderlich 	cmd->scan_nb_tone_thr = __cpu_to_le32(arg->scan_nb_tone_thr);
4284855aed12SSimon Wunderlich 	cmd->scan_str_bin_thr = __cpu_to_le32(arg->scan_str_bin_thr);
4285855aed12SSimon Wunderlich 	cmd->scan_wb_rpt_mode = __cpu_to_le32(arg->scan_wb_rpt_mode);
4286855aed12SSimon Wunderlich 	cmd->scan_rssi_rpt_mode = __cpu_to_le32(arg->scan_rssi_rpt_mode);
4287855aed12SSimon Wunderlich 	cmd->scan_rssi_thr = __cpu_to_le32(arg->scan_rssi_thr);
4288855aed12SSimon Wunderlich 	cmd->scan_pwr_format = __cpu_to_le32(arg->scan_pwr_format);
4289855aed12SSimon Wunderlich 	cmd->scan_rpt_mode = __cpu_to_le32(arg->scan_rpt_mode);
4290855aed12SSimon Wunderlich 	cmd->scan_bin_scale = __cpu_to_le32(arg->scan_bin_scale);
4291855aed12SSimon Wunderlich 	cmd->scan_dbm_adj = __cpu_to_le32(arg->scan_dbm_adj);
4292855aed12SSimon Wunderlich 	cmd->scan_chn_mask = __cpu_to_le32(arg->scan_chn_mask);
4293855aed12SSimon Wunderlich 
4294d7579d12SMichal Kazior 	return skb;
4295855aed12SSimon Wunderlich }
4296855aed12SSimon Wunderlich 
4297d7579d12SMichal Kazior static struct sk_buff *
4298d7579d12SMichal Kazior ath10k_wmi_op_gen_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id,
4299d7579d12SMichal Kazior 				       u32 trigger, u32 enable)
4300855aed12SSimon Wunderlich {
4301855aed12SSimon Wunderlich 	struct wmi_vdev_spectral_enable_cmd *cmd;
4302855aed12SSimon Wunderlich 	struct sk_buff *skb;
4303855aed12SSimon Wunderlich 
43047aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
4305855aed12SSimon Wunderlich 	if (!skb)
4306d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
4307855aed12SSimon Wunderlich 
4308855aed12SSimon Wunderlich 	cmd = (struct wmi_vdev_spectral_enable_cmd *)skb->data;
4309855aed12SSimon Wunderlich 	cmd->vdev_id = __cpu_to_le32(vdev_id);
4310855aed12SSimon Wunderlich 	cmd->trigger_cmd = __cpu_to_le32(trigger);
4311855aed12SSimon Wunderlich 	cmd->enable_cmd = __cpu_to_le32(enable);
4312855aed12SSimon Wunderlich 
4313d7579d12SMichal Kazior 	return skb;
4314855aed12SSimon Wunderlich }
4315855aed12SSimon Wunderlich 
4316d7579d12SMichal Kazior static struct sk_buff *
4317d7579d12SMichal Kazior ath10k_wmi_op_gen_peer_create(struct ath10k *ar, u32 vdev_id,
43185e3dd157SKalle Valo 			      const u8 peer_addr[ETH_ALEN])
43195e3dd157SKalle Valo {
43205e3dd157SKalle Valo 	struct wmi_peer_create_cmd *cmd;
43215e3dd157SKalle Valo 	struct sk_buff *skb;
43225e3dd157SKalle Valo 
43237aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
43245e3dd157SKalle Valo 	if (!skb)
4325d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
43265e3dd157SKalle Valo 
43275e3dd157SKalle Valo 	cmd = (struct wmi_peer_create_cmd *)skb->data;
43285e3dd157SKalle Valo 	cmd->vdev_id = __cpu_to_le32(vdev_id);
4329b25f32cbSKalle Valo 	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
43305e3dd157SKalle Valo 
43317aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
43325e3dd157SKalle Valo 		   "wmi peer create vdev_id %d peer_addr %pM\n",
43335e3dd157SKalle Valo 		   vdev_id, peer_addr);
4334d7579d12SMichal Kazior 	return skb;
43355e3dd157SKalle Valo }
43365e3dd157SKalle Valo 
4337d7579d12SMichal Kazior static struct sk_buff *
4338d7579d12SMichal Kazior ath10k_wmi_op_gen_peer_delete(struct ath10k *ar, u32 vdev_id,
43395e3dd157SKalle Valo 			      const u8 peer_addr[ETH_ALEN])
43405e3dd157SKalle Valo {
43415e3dd157SKalle Valo 	struct wmi_peer_delete_cmd *cmd;
43425e3dd157SKalle Valo 	struct sk_buff *skb;
43435e3dd157SKalle Valo 
43447aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
43455e3dd157SKalle Valo 	if (!skb)
4346d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
43475e3dd157SKalle Valo 
43485e3dd157SKalle Valo 	cmd = (struct wmi_peer_delete_cmd *)skb->data;
43495e3dd157SKalle Valo 	cmd->vdev_id = __cpu_to_le32(vdev_id);
4350b25f32cbSKalle Valo 	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
43515e3dd157SKalle Valo 
43527aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
43535e3dd157SKalle Valo 		   "wmi peer delete vdev_id %d peer_addr %pM\n",
43545e3dd157SKalle Valo 		   vdev_id, peer_addr);
4355d7579d12SMichal Kazior 	return skb;
43565e3dd157SKalle Valo }
43575e3dd157SKalle Valo 
4358d7579d12SMichal Kazior static struct sk_buff *
4359d7579d12SMichal Kazior ath10k_wmi_op_gen_peer_flush(struct ath10k *ar, u32 vdev_id,
43605e3dd157SKalle Valo 			     const u8 peer_addr[ETH_ALEN], u32 tid_bitmap)
43615e3dd157SKalle Valo {
43625e3dd157SKalle Valo 	struct wmi_peer_flush_tids_cmd *cmd;
43635e3dd157SKalle Valo 	struct sk_buff *skb;
43645e3dd157SKalle Valo 
43657aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
43665e3dd157SKalle Valo 	if (!skb)
4367d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
43685e3dd157SKalle Valo 
43695e3dd157SKalle Valo 	cmd = (struct wmi_peer_flush_tids_cmd *)skb->data;
43705e3dd157SKalle Valo 	cmd->vdev_id         = __cpu_to_le32(vdev_id);
43715e3dd157SKalle Valo 	cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap);
4372b25f32cbSKalle Valo 	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
43735e3dd157SKalle Valo 
43747aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
43755e3dd157SKalle Valo 		   "wmi peer flush vdev_id %d peer_addr %pM tids %08x\n",
43765e3dd157SKalle Valo 		   vdev_id, peer_addr, tid_bitmap);
4377d7579d12SMichal Kazior 	return skb;
43785e3dd157SKalle Valo }
43795e3dd157SKalle Valo 
4380d7579d12SMichal Kazior static struct sk_buff *
4381d7579d12SMichal Kazior ath10k_wmi_op_gen_peer_set_param(struct ath10k *ar, u32 vdev_id,
4382d7579d12SMichal Kazior 				 const u8 *peer_addr,
4383d7579d12SMichal Kazior 				 enum wmi_peer_param param_id,
43845e3dd157SKalle Valo 				 u32 param_value)
43855e3dd157SKalle Valo {
43865e3dd157SKalle Valo 	struct wmi_peer_set_param_cmd *cmd;
43875e3dd157SKalle Valo 	struct sk_buff *skb;
43885e3dd157SKalle Valo 
43897aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
43905e3dd157SKalle Valo 	if (!skb)
4391d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
43925e3dd157SKalle Valo 
43935e3dd157SKalle Valo 	cmd = (struct wmi_peer_set_param_cmd *)skb->data;
43945e3dd157SKalle Valo 	cmd->vdev_id     = __cpu_to_le32(vdev_id);
43955e3dd157SKalle Valo 	cmd->param_id    = __cpu_to_le32(param_id);
43965e3dd157SKalle Valo 	cmd->param_value = __cpu_to_le32(param_value);
4397b25f32cbSKalle Valo 	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
43985e3dd157SKalle Valo 
43997aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
44005e3dd157SKalle Valo 		   "wmi vdev %d peer 0x%pM set param %d value %d\n",
44015e3dd157SKalle Valo 		   vdev_id, peer_addr, param_id, param_value);
4402d7579d12SMichal Kazior 	return skb;
44035e3dd157SKalle Valo }
44045e3dd157SKalle Valo 
4405d7579d12SMichal Kazior static struct sk_buff *
4406d7579d12SMichal Kazior ath10k_wmi_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id,
44075e3dd157SKalle Valo 			     enum wmi_sta_ps_mode psmode)
44085e3dd157SKalle Valo {
44095e3dd157SKalle Valo 	struct wmi_sta_powersave_mode_cmd *cmd;
44105e3dd157SKalle Valo 	struct sk_buff *skb;
44115e3dd157SKalle Valo 
44127aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
44135e3dd157SKalle Valo 	if (!skb)
4414d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
44155e3dd157SKalle Valo 
44165e3dd157SKalle Valo 	cmd = (struct wmi_sta_powersave_mode_cmd *)skb->data;
44175e3dd157SKalle Valo 	cmd->vdev_id     = __cpu_to_le32(vdev_id);
44185e3dd157SKalle Valo 	cmd->sta_ps_mode = __cpu_to_le32(psmode);
44195e3dd157SKalle Valo 
44207aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
44215e3dd157SKalle Valo 		   "wmi set powersave id 0x%x mode %d\n",
44225e3dd157SKalle Valo 		   vdev_id, psmode);
4423d7579d12SMichal Kazior 	return skb;
44245e3dd157SKalle Valo }
44255e3dd157SKalle Valo 
4426d7579d12SMichal Kazior static struct sk_buff *
4427d7579d12SMichal Kazior ath10k_wmi_op_gen_set_sta_ps(struct ath10k *ar, u32 vdev_id,
44285e3dd157SKalle Valo 			     enum wmi_sta_powersave_param param_id,
44295e3dd157SKalle Valo 			     u32 value)
44305e3dd157SKalle Valo {
44315e3dd157SKalle Valo 	struct wmi_sta_powersave_param_cmd *cmd;
44325e3dd157SKalle Valo 	struct sk_buff *skb;
44335e3dd157SKalle Valo 
44347aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
44355e3dd157SKalle Valo 	if (!skb)
4436d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
44375e3dd157SKalle Valo 
44385e3dd157SKalle Valo 	cmd = (struct wmi_sta_powersave_param_cmd *)skb->data;
44395e3dd157SKalle Valo 	cmd->vdev_id     = __cpu_to_le32(vdev_id);
44405e3dd157SKalle Valo 	cmd->param_id    = __cpu_to_le32(param_id);
44415e3dd157SKalle Valo 	cmd->param_value = __cpu_to_le32(value);
44425e3dd157SKalle Valo 
44437aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
44445e3dd157SKalle Valo 		   "wmi sta ps param vdev_id 0x%x param %d value %d\n",
44455e3dd157SKalle Valo 		   vdev_id, param_id, value);
4446d7579d12SMichal Kazior 	return skb;
44475e3dd157SKalle Valo }
44485e3dd157SKalle Valo 
4449d7579d12SMichal Kazior static struct sk_buff *
4450d7579d12SMichal Kazior ath10k_wmi_op_gen_set_ap_ps(struct ath10k *ar, u32 vdev_id, const u8 *mac,
44515e3dd157SKalle Valo 			    enum wmi_ap_ps_peer_param param_id, u32 value)
44525e3dd157SKalle Valo {
44535e3dd157SKalle Valo 	struct wmi_ap_ps_peer_cmd *cmd;
44545e3dd157SKalle Valo 	struct sk_buff *skb;
44555e3dd157SKalle Valo 
44565e3dd157SKalle Valo 	if (!mac)
4457d7579d12SMichal Kazior 		return ERR_PTR(-EINVAL);
44585e3dd157SKalle Valo 
44597aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
44605e3dd157SKalle Valo 	if (!skb)
4461d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
44625e3dd157SKalle Valo 
44635e3dd157SKalle Valo 	cmd = (struct wmi_ap_ps_peer_cmd *)skb->data;
44645e3dd157SKalle Valo 	cmd->vdev_id = __cpu_to_le32(vdev_id);
44655e3dd157SKalle Valo 	cmd->param_id = __cpu_to_le32(param_id);
44665e3dd157SKalle Valo 	cmd->param_value = __cpu_to_le32(value);
4467b25f32cbSKalle Valo 	ether_addr_copy(cmd->peer_macaddr.addr, mac);
44685e3dd157SKalle Valo 
44697aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
44705e3dd157SKalle Valo 		   "wmi ap ps param vdev_id 0x%X param %d value %d mac_addr %pM\n",
44715e3dd157SKalle Valo 		   vdev_id, param_id, value, mac);
4472d7579d12SMichal Kazior 	return skb;
44735e3dd157SKalle Valo }
44745e3dd157SKalle Valo 
4475d7579d12SMichal Kazior static struct sk_buff *
4476d7579d12SMichal Kazior ath10k_wmi_op_gen_scan_chan_list(struct ath10k *ar,
44775e3dd157SKalle Valo 				 const struct wmi_scan_chan_list_arg *arg)
44785e3dd157SKalle Valo {
44795e3dd157SKalle Valo 	struct wmi_scan_chan_list_cmd *cmd;
44805e3dd157SKalle Valo 	struct sk_buff *skb;
44815e3dd157SKalle Valo 	struct wmi_channel_arg *ch;
44825e3dd157SKalle Valo 	struct wmi_channel *ci;
44835e3dd157SKalle Valo 	int len;
44845e3dd157SKalle Valo 	int i;
44855e3dd157SKalle Valo 
44865e3dd157SKalle Valo 	len = sizeof(*cmd) + arg->n_channels * sizeof(struct wmi_channel);
44875e3dd157SKalle Valo 
44887aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
44895e3dd157SKalle Valo 	if (!skb)
4490d7579d12SMichal Kazior 		return ERR_PTR(-EINVAL);
44915e3dd157SKalle Valo 
44925e3dd157SKalle Valo 	cmd = (struct wmi_scan_chan_list_cmd *)skb->data;
44935e3dd157SKalle Valo 	cmd->num_scan_chans = __cpu_to_le32(arg->n_channels);
44945e3dd157SKalle Valo 
44955e3dd157SKalle Valo 	for (i = 0; i < arg->n_channels; i++) {
44965e3dd157SKalle Valo 		ch = &arg->channels[i];
44975e3dd157SKalle Valo 		ci = &cmd->chan_info[i];
44985e3dd157SKalle Valo 
44992d66721cSMichal Kazior 		ath10k_wmi_put_wmi_channel(ci, ch);
45005e3dd157SKalle Valo 	}
45015e3dd157SKalle Valo 
4502d7579d12SMichal Kazior 	return skb;
45035e3dd157SKalle Valo }
45045e3dd157SKalle Valo 
450524c88f78SMichal Kazior static void
450624c88f78SMichal Kazior ath10k_wmi_peer_assoc_fill(struct ath10k *ar, void *buf,
45075e3dd157SKalle Valo 			   const struct wmi_peer_assoc_complete_arg *arg)
45085e3dd157SKalle Valo {
450924c88f78SMichal Kazior 	struct wmi_common_peer_assoc_complete_cmd *cmd = buf;
45105e3dd157SKalle Valo 
45115e3dd157SKalle Valo 	cmd->vdev_id            = __cpu_to_le32(arg->vdev_id);
45125e3dd157SKalle Valo 	cmd->peer_new_assoc     = __cpu_to_le32(arg->peer_reassoc ? 0 : 1);
45135e3dd157SKalle Valo 	cmd->peer_associd       = __cpu_to_le32(arg->peer_aid);
45145e3dd157SKalle Valo 	cmd->peer_flags         = __cpu_to_le32(arg->peer_flags);
45155e3dd157SKalle Valo 	cmd->peer_caps          = __cpu_to_le32(arg->peer_caps);
45165e3dd157SKalle Valo 	cmd->peer_listen_intval = __cpu_to_le32(arg->peer_listen_intval);
45175e3dd157SKalle Valo 	cmd->peer_ht_caps       = __cpu_to_le32(arg->peer_ht_caps);
45185e3dd157SKalle Valo 	cmd->peer_max_mpdu      = __cpu_to_le32(arg->peer_max_mpdu);
45195e3dd157SKalle Valo 	cmd->peer_mpdu_density  = __cpu_to_le32(arg->peer_mpdu_density);
45205e3dd157SKalle Valo 	cmd->peer_rate_caps     = __cpu_to_le32(arg->peer_rate_caps);
45215e3dd157SKalle Valo 	cmd->peer_nss           = __cpu_to_le32(arg->peer_num_spatial_streams);
45225e3dd157SKalle Valo 	cmd->peer_vht_caps      = __cpu_to_le32(arg->peer_vht_caps);
45235e3dd157SKalle Valo 	cmd->peer_phymode       = __cpu_to_le32(arg->peer_phymode);
45245e3dd157SKalle Valo 
4525b25f32cbSKalle Valo 	ether_addr_copy(cmd->peer_macaddr.addr, arg->addr);
45265e3dd157SKalle Valo 
45275e3dd157SKalle Valo 	cmd->peer_legacy_rates.num_rates =
45285e3dd157SKalle Valo 		__cpu_to_le32(arg->peer_legacy_rates.num_rates);
45295e3dd157SKalle Valo 	memcpy(cmd->peer_legacy_rates.rates, arg->peer_legacy_rates.rates,
45305e3dd157SKalle Valo 	       arg->peer_legacy_rates.num_rates);
45315e3dd157SKalle Valo 
45325e3dd157SKalle Valo 	cmd->peer_ht_rates.num_rates =
45335e3dd157SKalle Valo 		__cpu_to_le32(arg->peer_ht_rates.num_rates);
45345e3dd157SKalle Valo 	memcpy(cmd->peer_ht_rates.rates, arg->peer_ht_rates.rates,
45355e3dd157SKalle Valo 	       arg->peer_ht_rates.num_rates);
45365e3dd157SKalle Valo 
45375e3dd157SKalle Valo 	cmd->peer_vht_rates.rx_max_rate =
45385e3dd157SKalle Valo 		__cpu_to_le32(arg->peer_vht_rates.rx_max_rate);
45395e3dd157SKalle Valo 	cmd->peer_vht_rates.rx_mcs_set =
45405e3dd157SKalle Valo 		__cpu_to_le32(arg->peer_vht_rates.rx_mcs_set);
45415e3dd157SKalle Valo 	cmd->peer_vht_rates.tx_max_rate =
45425e3dd157SKalle Valo 		__cpu_to_le32(arg->peer_vht_rates.tx_max_rate);
45435e3dd157SKalle Valo 	cmd->peer_vht_rates.tx_mcs_set =
45445e3dd157SKalle Valo 		__cpu_to_le32(arg->peer_vht_rates.tx_mcs_set);
454524c88f78SMichal Kazior }
454624c88f78SMichal Kazior 
454724c88f78SMichal Kazior static void
454824c88f78SMichal Kazior ath10k_wmi_peer_assoc_fill_main(struct ath10k *ar, void *buf,
454924c88f78SMichal Kazior 				const struct wmi_peer_assoc_complete_arg *arg)
455024c88f78SMichal Kazior {
455124c88f78SMichal Kazior 	struct wmi_main_peer_assoc_complete_cmd *cmd = buf;
455224c88f78SMichal Kazior 
455324c88f78SMichal Kazior 	ath10k_wmi_peer_assoc_fill(ar, buf, arg);
455424c88f78SMichal Kazior 	memset(cmd->peer_ht_info, 0, sizeof(cmd->peer_ht_info));
455524c88f78SMichal Kazior }
455624c88f78SMichal Kazior 
455724c88f78SMichal Kazior static void
455824c88f78SMichal Kazior ath10k_wmi_peer_assoc_fill_10_1(struct ath10k *ar, void *buf,
455924c88f78SMichal Kazior 				const struct wmi_peer_assoc_complete_arg *arg)
456024c88f78SMichal Kazior {
456124c88f78SMichal Kazior 	ath10k_wmi_peer_assoc_fill(ar, buf, arg);
456224c88f78SMichal Kazior }
456324c88f78SMichal Kazior 
456424c88f78SMichal Kazior static void
456524c88f78SMichal Kazior ath10k_wmi_peer_assoc_fill_10_2(struct ath10k *ar, void *buf,
456624c88f78SMichal Kazior 				const struct wmi_peer_assoc_complete_arg *arg)
456724c88f78SMichal Kazior {
456824c88f78SMichal Kazior 	struct wmi_10_2_peer_assoc_complete_cmd *cmd = buf;
456924c88f78SMichal Kazior 	int max_mcs, max_nss;
457024c88f78SMichal Kazior 	u32 info0;
457124c88f78SMichal Kazior 
457224c88f78SMichal Kazior 	/* TODO: Is using max values okay with firmware? */
457324c88f78SMichal Kazior 	max_mcs = 0xf;
457424c88f78SMichal Kazior 	max_nss = 0xf;
457524c88f78SMichal Kazior 
457624c88f78SMichal Kazior 	info0 = SM(max_mcs, WMI_PEER_ASSOC_INFO0_MAX_MCS_IDX) |
457724c88f78SMichal Kazior 		SM(max_nss, WMI_PEER_ASSOC_INFO0_MAX_NSS);
457824c88f78SMichal Kazior 
457924c88f78SMichal Kazior 	ath10k_wmi_peer_assoc_fill(ar, buf, arg);
458024c88f78SMichal Kazior 	cmd->info0 = __cpu_to_le32(info0);
458124c88f78SMichal Kazior }
458224c88f78SMichal Kazior 
4583d7579d12SMichal Kazior static int
4584d7579d12SMichal Kazior ath10k_wmi_peer_assoc_check_arg(const struct wmi_peer_assoc_complete_arg *arg)
458524c88f78SMichal Kazior {
458624c88f78SMichal Kazior 	if (arg->peer_mpdu_density > 16)
458724c88f78SMichal Kazior 		return -EINVAL;
458824c88f78SMichal Kazior 	if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES)
458924c88f78SMichal Kazior 		return -EINVAL;
459024c88f78SMichal Kazior 	if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES)
459124c88f78SMichal Kazior 		return -EINVAL;
459224c88f78SMichal Kazior 
4593d7579d12SMichal Kazior 	return 0;
459424c88f78SMichal Kazior }
459524c88f78SMichal Kazior 
4596d7579d12SMichal Kazior static struct sk_buff *
4597d7579d12SMichal Kazior ath10k_wmi_op_gen_peer_assoc(struct ath10k *ar,
4598d7579d12SMichal Kazior 			     const struct wmi_peer_assoc_complete_arg *arg)
4599d7579d12SMichal Kazior {
4600d7579d12SMichal Kazior 	size_t len = sizeof(struct wmi_main_peer_assoc_complete_cmd);
4601d7579d12SMichal Kazior 	struct sk_buff *skb;
4602d7579d12SMichal Kazior 	int ret;
4603d7579d12SMichal Kazior 
4604d7579d12SMichal Kazior 	ret = ath10k_wmi_peer_assoc_check_arg(arg);
4605d7579d12SMichal Kazior 	if (ret)
4606d7579d12SMichal Kazior 		return ERR_PTR(ret);
4607d7579d12SMichal Kazior 
46087aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
460924c88f78SMichal Kazior 	if (!skb)
4610d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
461124c88f78SMichal Kazior 
461224c88f78SMichal Kazior 	ath10k_wmi_peer_assoc_fill_main(ar, skb->data, arg);
46135e3dd157SKalle Valo 
46147aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
461544d6fa90SChun-Yeow Yeoh 		   "wmi peer assoc vdev %d addr %pM (%s)\n",
461644d6fa90SChun-Yeow Yeoh 		   arg->vdev_id, arg->addr,
461744d6fa90SChun-Yeow Yeoh 		   arg->peer_reassoc ? "reassociate" : "new");
4618d7579d12SMichal Kazior 	return skb;
4619d7579d12SMichal Kazior }
4620d7579d12SMichal Kazior 
4621d7579d12SMichal Kazior static struct sk_buff *
4622d7579d12SMichal Kazior ath10k_wmi_10_1_op_gen_peer_assoc(struct ath10k *ar,
4623d7579d12SMichal Kazior 				  const struct wmi_peer_assoc_complete_arg *arg)
4624d7579d12SMichal Kazior {
4625d7579d12SMichal Kazior 	size_t len = sizeof(struct wmi_10_1_peer_assoc_complete_cmd);
4626d7579d12SMichal Kazior 	struct sk_buff *skb;
4627d7579d12SMichal Kazior 	int ret;
4628d7579d12SMichal Kazior 
4629d7579d12SMichal Kazior 	ret = ath10k_wmi_peer_assoc_check_arg(arg);
4630d7579d12SMichal Kazior 	if (ret)
4631d7579d12SMichal Kazior 		return ERR_PTR(ret);
4632d7579d12SMichal Kazior 
4633d7579d12SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
4634d7579d12SMichal Kazior 	if (!skb)
4635d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
4636d7579d12SMichal Kazior 
4637d7579d12SMichal Kazior 	ath10k_wmi_peer_assoc_fill_10_1(ar, skb->data, arg);
4638d7579d12SMichal Kazior 
4639d7579d12SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
4640d7579d12SMichal Kazior 		   "wmi peer assoc vdev %d addr %pM (%s)\n",
4641d7579d12SMichal Kazior 		   arg->vdev_id, arg->addr,
4642d7579d12SMichal Kazior 		   arg->peer_reassoc ? "reassociate" : "new");
4643d7579d12SMichal Kazior 	return skb;
4644d7579d12SMichal Kazior }
4645d7579d12SMichal Kazior 
4646d7579d12SMichal Kazior static struct sk_buff *
4647d7579d12SMichal Kazior ath10k_wmi_10_2_op_gen_peer_assoc(struct ath10k *ar,
4648d7579d12SMichal Kazior 				  const struct wmi_peer_assoc_complete_arg *arg)
4649d7579d12SMichal Kazior {
4650d7579d12SMichal Kazior 	size_t len = sizeof(struct wmi_10_2_peer_assoc_complete_cmd);
4651d7579d12SMichal Kazior 	struct sk_buff *skb;
4652d7579d12SMichal Kazior 	int ret;
4653d7579d12SMichal Kazior 
4654d7579d12SMichal Kazior 	ret = ath10k_wmi_peer_assoc_check_arg(arg);
4655d7579d12SMichal Kazior 	if (ret)
4656d7579d12SMichal Kazior 		return ERR_PTR(ret);
4657d7579d12SMichal Kazior 
4658d7579d12SMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, len);
4659d7579d12SMichal Kazior 	if (!skb)
4660d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
4661d7579d12SMichal Kazior 
4662d7579d12SMichal Kazior 	ath10k_wmi_peer_assoc_fill_10_2(ar, skb->data, arg);
4663d7579d12SMichal Kazior 
4664d7579d12SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
4665d7579d12SMichal Kazior 		   "wmi peer assoc vdev %d addr %pM (%s)\n",
4666d7579d12SMichal Kazior 		   arg->vdev_id, arg->addr,
4667d7579d12SMichal Kazior 		   arg->peer_reassoc ? "reassociate" : "new");
4668d7579d12SMichal Kazior 	return skb;
46695e3dd157SKalle Valo }
46705e3dd157SKalle Valo 
4671a57a6a27SRajkumar Manoharan static struct sk_buff *
4672a57a6a27SRajkumar Manoharan ath10k_wmi_10_2_op_gen_pdev_get_temperature(struct ath10k *ar)
4673a57a6a27SRajkumar Manoharan {
4674a57a6a27SRajkumar Manoharan 	struct sk_buff *skb;
4675a57a6a27SRajkumar Manoharan 
4676a57a6a27SRajkumar Manoharan 	skb = ath10k_wmi_alloc_skb(ar, 0);
4677a57a6a27SRajkumar Manoharan 	if (!skb)
4678a57a6a27SRajkumar Manoharan 		return ERR_PTR(-ENOMEM);
4679a57a6a27SRajkumar Manoharan 
4680a57a6a27SRajkumar Manoharan 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi pdev get temperature\n");
4681a57a6a27SRajkumar Manoharan 	return skb;
4682a57a6a27SRajkumar Manoharan }
4683a57a6a27SRajkumar Manoharan 
4684748afc47SMichal Kazior /* This function assumes the beacon is already DMA mapped */
4685d7579d12SMichal Kazior static struct sk_buff *
4686d7579d12SMichal Kazior ath10k_wmi_op_gen_beacon_dma(struct ath10k_vif *arvif)
46875e3dd157SKalle Valo {
4688d7579d12SMichal Kazior 	struct ath10k *ar = arvif->ar;
4689748afc47SMichal Kazior 	struct wmi_bcn_tx_ref_cmd *cmd;
46905e3dd157SKalle Valo 	struct sk_buff *skb;
4691748afc47SMichal Kazior 	struct sk_buff *beacon = arvif->beacon;
4692748afc47SMichal Kazior 	struct ieee80211_hdr *hdr;
4693748afc47SMichal Kazior 	u16 fc;
46945e3dd157SKalle Valo 
46957aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
46965e3dd157SKalle Valo 	if (!skb)
4697d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
46985e3dd157SKalle Valo 
4699748afc47SMichal Kazior 	hdr = (struct ieee80211_hdr *)beacon->data;
4700748afc47SMichal Kazior 	fc = le16_to_cpu(hdr->frame_control);
47015e3dd157SKalle Valo 
4702748afc47SMichal Kazior 	cmd = (struct wmi_bcn_tx_ref_cmd *)skb->data;
4703748afc47SMichal Kazior 	cmd->vdev_id = __cpu_to_le32(arvif->vdev_id);
4704748afc47SMichal Kazior 	cmd->data_len = __cpu_to_le32(beacon->len);
4705748afc47SMichal Kazior 	cmd->data_ptr = __cpu_to_le32(ATH10K_SKB_CB(beacon)->paddr);
4706748afc47SMichal Kazior 	cmd->msdu_id = 0;
4707748afc47SMichal Kazior 	cmd->frame_control = __cpu_to_le32(fc);
4708748afc47SMichal Kazior 	cmd->flags = 0;
470924c88f78SMichal Kazior 	cmd->antenna_mask = __cpu_to_le32(WMI_BCN_TX_REF_DEF_ANTENNA);
4710748afc47SMichal Kazior 
4711748afc47SMichal Kazior 	if (ATH10K_SKB_CB(beacon)->bcn.dtim_zero)
4712748afc47SMichal Kazior 		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO);
4713748afc47SMichal Kazior 
4714748afc47SMichal Kazior 	if (ATH10K_SKB_CB(beacon)->bcn.deliver_cab)
4715748afc47SMichal Kazior 		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB);
4716748afc47SMichal Kazior 
4717d7579d12SMichal Kazior 	return skb;
47185e3dd157SKalle Valo }
47195e3dd157SKalle Valo 
47200226d602SMichal Kazior void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params,
47215e3dd157SKalle Valo 				   const struct wmi_wmm_params_arg *arg)
47225e3dd157SKalle Valo {
47235e3dd157SKalle Valo 	params->cwmin  = __cpu_to_le32(arg->cwmin);
47245e3dd157SKalle Valo 	params->cwmax  = __cpu_to_le32(arg->cwmax);
47255e3dd157SKalle Valo 	params->aifs   = __cpu_to_le32(arg->aifs);
47265e3dd157SKalle Valo 	params->txop   = __cpu_to_le32(arg->txop);
47275e3dd157SKalle Valo 	params->acm    = __cpu_to_le32(arg->acm);
47285e3dd157SKalle Valo 	params->no_ack = __cpu_to_le32(arg->no_ack);
47295e3dd157SKalle Valo }
47305e3dd157SKalle Valo 
4731d7579d12SMichal Kazior static struct sk_buff *
4732d7579d12SMichal Kazior ath10k_wmi_op_gen_pdev_set_wmm(struct ath10k *ar,
47335e3dd157SKalle Valo 			       const struct wmi_pdev_set_wmm_params_arg *arg)
47345e3dd157SKalle Valo {
47355e3dd157SKalle Valo 	struct wmi_pdev_set_wmm_params *cmd;
47365e3dd157SKalle Valo 	struct sk_buff *skb;
47375e3dd157SKalle Valo 
47387aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
47395e3dd157SKalle Valo 	if (!skb)
4740d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
47415e3dd157SKalle Valo 
47425e3dd157SKalle Valo 	cmd = (struct wmi_pdev_set_wmm_params *)skb->data;
47435e3dd157SKalle Valo 	ath10k_wmi_pdev_set_wmm_param(&cmd->ac_be, &arg->ac_be);
47445e3dd157SKalle Valo 	ath10k_wmi_pdev_set_wmm_param(&cmd->ac_bk, &arg->ac_bk);
47455e3dd157SKalle Valo 	ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vi, &arg->ac_vi);
47465e3dd157SKalle Valo 	ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vo, &arg->ac_vo);
47475e3dd157SKalle Valo 
47487aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi pdev set wmm params\n");
4749d7579d12SMichal Kazior 	return skb;
47505e3dd157SKalle Valo }
47515e3dd157SKalle Valo 
4752d7579d12SMichal Kazior static struct sk_buff *
4753d7579d12SMichal Kazior ath10k_wmi_op_gen_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id)
47545e3dd157SKalle Valo {
47555e3dd157SKalle Valo 	struct wmi_request_stats_cmd *cmd;
47565e3dd157SKalle Valo 	struct sk_buff *skb;
47575e3dd157SKalle Valo 
47587aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
47595e3dd157SKalle Valo 	if (!skb)
4760d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
47615e3dd157SKalle Valo 
47625e3dd157SKalle Valo 	cmd = (struct wmi_request_stats_cmd *)skb->data;
47635e3dd157SKalle Valo 	cmd->stats_id = __cpu_to_le32(stats_id);
47645e3dd157SKalle Valo 
47657aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi request stats %d\n", (int)stats_id);
4766d7579d12SMichal Kazior 	return skb;
47675e3dd157SKalle Valo }
47689cfbce75SMichal Kazior 
4769d7579d12SMichal Kazior static struct sk_buff *
4770d7579d12SMichal Kazior ath10k_wmi_op_gen_force_fw_hang(struct ath10k *ar,
47719cfbce75SMichal Kazior 				enum wmi_force_fw_hang_type type, u32 delay_ms)
47729cfbce75SMichal Kazior {
47739cfbce75SMichal Kazior 	struct wmi_force_fw_hang_cmd *cmd;
47749cfbce75SMichal Kazior 	struct sk_buff *skb;
47759cfbce75SMichal Kazior 
47767aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
47779cfbce75SMichal Kazior 	if (!skb)
4778d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
47799cfbce75SMichal Kazior 
47809cfbce75SMichal Kazior 	cmd = (struct wmi_force_fw_hang_cmd *)skb->data;
47819cfbce75SMichal Kazior 	cmd->type = __cpu_to_le32(type);
47829cfbce75SMichal Kazior 	cmd->delay_ms = __cpu_to_le32(delay_ms);
47839cfbce75SMichal Kazior 
47847aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi force fw hang %d delay %d\n",
47859cfbce75SMichal Kazior 		   type, delay_ms);
4786d7579d12SMichal Kazior 	return skb;
47879cfbce75SMichal Kazior }
4788f118a3e5SKalle Valo 
4789d7579d12SMichal Kazior static struct sk_buff *
4790d7579d12SMichal Kazior ath10k_wmi_op_gen_dbglog_cfg(struct ath10k *ar, u32 module_enable)
4791f118a3e5SKalle Valo {
4792f118a3e5SKalle Valo 	struct wmi_dbglog_cfg_cmd *cmd;
4793f118a3e5SKalle Valo 	struct sk_buff *skb;
4794f118a3e5SKalle Valo 	u32 cfg;
4795f118a3e5SKalle Valo 
47967aa7a72aSMichal Kazior 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
4797f118a3e5SKalle Valo 	if (!skb)
4798d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
4799f118a3e5SKalle Valo 
4800f118a3e5SKalle Valo 	cmd = (struct wmi_dbglog_cfg_cmd *)skb->data;
4801f118a3e5SKalle Valo 
4802f118a3e5SKalle Valo 	if (module_enable) {
4803f118a3e5SKalle Valo 		cfg = SM(ATH10K_DBGLOG_LEVEL_VERBOSE,
4804f118a3e5SKalle Valo 			 ATH10K_DBGLOG_CFG_LOG_LVL);
4805f118a3e5SKalle Valo 	} else {
4806f118a3e5SKalle Valo 		/* set back defaults, all modules with WARN level */
4807f118a3e5SKalle Valo 		cfg = SM(ATH10K_DBGLOG_LEVEL_WARN,
4808f118a3e5SKalle Valo 			 ATH10K_DBGLOG_CFG_LOG_LVL);
4809f118a3e5SKalle Valo 		module_enable = ~0;
4810f118a3e5SKalle Valo 	}
4811f118a3e5SKalle Valo 
4812f118a3e5SKalle Valo 	cmd->module_enable = __cpu_to_le32(module_enable);
4813f118a3e5SKalle Valo 	cmd->module_valid = __cpu_to_le32(~0);
4814f118a3e5SKalle Valo 	cmd->config_enable = __cpu_to_le32(cfg);
4815f118a3e5SKalle Valo 	cmd->config_valid = __cpu_to_le32(ATH10K_DBGLOG_CFG_LOG_LVL_MASK);
4816f118a3e5SKalle Valo 
48177aa7a72aSMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI,
4818f118a3e5SKalle Valo 		   "wmi dbglog cfg modules %08x %08x config %08x %08x\n",
4819f118a3e5SKalle Valo 		   __le32_to_cpu(cmd->module_enable),
4820f118a3e5SKalle Valo 		   __le32_to_cpu(cmd->module_valid),
4821f118a3e5SKalle Valo 		   __le32_to_cpu(cmd->config_enable),
4822f118a3e5SKalle Valo 		   __le32_to_cpu(cmd->config_valid));
4823d7579d12SMichal Kazior 	return skb;
4824f118a3e5SKalle Valo }
4825b79b9baaSMichal Kazior 
4826d7579d12SMichal Kazior static struct sk_buff *
4827d7579d12SMichal Kazior ath10k_wmi_op_gen_pktlog_enable(struct ath10k *ar, u32 ev_bitmap)
482890174455SRajkumar Manoharan {
482990174455SRajkumar Manoharan 	struct wmi_pdev_pktlog_enable_cmd *cmd;
483090174455SRajkumar Manoharan 	struct sk_buff *skb;
483190174455SRajkumar Manoharan 
483290174455SRajkumar Manoharan 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
483390174455SRajkumar Manoharan 	if (!skb)
4834d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
483590174455SRajkumar Manoharan 
483690174455SRajkumar Manoharan 	ev_bitmap &= ATH10K_PKTLOG_ANY;
483790174455SRajkumar Manoharan 
483890174455SRajkumar Manoharan 	cmd = (struct wmi_pdev_pktlog_enable_cmd *)skb->data;
483990174455SRajkumar Manoharan 	cmd->ev_bitmap = __cpu_to_le32(ev_bitmap);
4840d7579d12SMichal Kazior 
4841d7579d12SMichal Kazior 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi enable pktlog filter 0x%08x\n",
4842d7579d12SMichal Kazior 		   ev_bitmap);
4843d7579d12SMichal Kazior 	return skb;
484490174455SRajkumar Manoharan }
484590174455SRajkumar Manoharan 
4846d7579d12SMichal Kazior static struct sk_buff *
4847d7579d12SMichal Kazior ath10k_wmi_op_gen_pktlog_disable(struct ath10k *ar)
484890174455SRajkumar Manoharan {
484990174455SRajkumar Manoharan 	struct sk_buff *skb;
485090174455SRajkumar Manoharan 
485190174455SRajkumar Manoharan 	skb = ath10k_wmi_alloc_skb(ar, 0);
485290174455SRajkumar Manoharan 	if (!skb)
4853d7579d12SMichal Kazior 		return ERR_PTR(-ENOMEM);
485490174455SRajkumar Manoharan 
485590174455SRajkumar Manoharan 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi disable pktlog\n");
4856d7579d12SMichal Kazior 	return skb;
485790174455SRajkumar Manoharan }
485890174455SRajkumar Manoharan 
4859ffdd738dSRajkumar Manoharan static struct sk_buff *
4860ffdd738dSRajkumar Manoharan ath10k_wmi_op_gen_pdev_set_quiet_mode(struct ath10k *ar, u32 period,
4861ffdd738dSRajkumar Manoharan 				      u32 duration, u32 next_offset,
4862ffdd738dSRajkumar Manoharan 				      u32 enabled)
4863ffdd738dSRajkumar Manoharan {
4864ffdd738dSRajkumar Manoharan 	struct wmi_pdev_set_quiet_cmd *cmd;
4865ffdd738dSRajkumar Manoharan 	struct sk_buff *skb;
4866ffdd738dSRajkumar Manoharan 
4867ffdd738dSRajkumar Manoharan 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
4868ffdd738dSRajkumar Manoharan 	if (!skb)
4869ffdd738dSRajkumar Manoharan 		return ERR_PTR(-ENOMEM);
4870ffdd738dSRajkumar Manoharan 
4871ffdd738dSRajkumar Manoharan 	cmd = (struct wmi_pdev_set_quiet_cmd *)skb->data;
4872ffdd738dSRajkumar Manoharan 	cmd->period = __cpu_to_le32(period);
4873ffdd738dSRajkumar Manoharan 	cmd->duration = __cpu_to_le32(duration);
4874ffdd738dSRajkumar Manoharan 	cmd->next_start = __cpu_to_le32(next_offset);
4875ffdd738dSRajkumar Manoharan 	cmd->enabled = __cpu_to_le32(enabled);
4876ffdd738dSRajkumar Manoharan 
4877ffdd738dSRajkumar Manoharan 	ath10k_dbg(ar, ATH10K_DBG_WMI,
4878ffdd738dSRajkumar Manoharan 		   "wmi quiet param: period %u duration %u enabled %d\n",
4879ffdd738dSRajkumar Manoharan 		   period, duration, enabled);
4880ffdd738dSRajkumar Manoharan 	return skb;
4881ffdd738dSRajkumar Manoharan }
4882ffdd738dSRajkumar Manoharan 
4883dc8ab278SRajkumar Manoharan static struct sk_buff *
4884dc8ab278SRajkumar Manoharan ath10k_wmi_op_gen_addba_clear_resp(struct ath10k *ar, u32 vdev_id,
4885dc8ab278SRajkumar Manoharan 				   const u8 *mac)
4886dc8ab278SRajkumar Manoharan {
4887dc8ab278SRajkumar Manoharan 	struct wmi_addba_clear_resp_cmd *cmd;
4888dc8ab278SRajkumar Manoharan 	struct sk_buff *skb;
4889dc8ab278SRajkumar Manoharan 
4890dc8ab278SRajkumar Manoharan 	if (!mac)
4891dc8ab278SRajkumar Manoharan 		return ERR_PTR(-EINVAL);
4892dc8ab278SRajkumar Manoharan 
4893dc8ab278SRajkumar Manoharan 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
4894dc8ab278SRajkumar Manoharan 	if (!skb)
4895dc8ab278SRajkumar Manoharan 		return ERR_PTR(-ENOMEM);
4896dc8ab278SRajkumar Manoharan 
4897dc8ab278SRajkumar Manoharan 	cmd = (struct wmi_addba_clear_resp_cmd *)skb->data;
4898dc8ab278SRajkumar Manoharan 	cmd->vdev_id = __cpu_to_le32(vdev_id);
4899dc8ab278SRajkumar Manoharan 	ether_addr_copy(cmd->peer_macaddr.addr, mac);
4900dc8ab278SRajkumar Manoharan 
4901dc8ab278SRajkumar Manoharan 	ath10k_dbg(ar, ATH10K_DBG_WMI,
4902dc8ab278SRajkumar Manoharan 		   "wmi addba clear resp vdev_id 0x%X mac_addr %pM\n",
4903dc8ab278SRajkumar Manoharan 		   vdev_id, mac);
4904dc8ab278SRajkumar Manoharan 	return skb;
4905dc8ab278SRajkumar Manoharan }
4906dc8ab278SRajkumar Manoharan 
490765c0893dSRajkumar Manoharan static struct sk_buff *
490865c0893dSRajkumar Manoharan ath10k_wmi_op_gen_addba_send(struct ath10k *ar, u32 vdev_id, const u8 *mac,
490965c0893dSRajkumar Manoharan 			     u32 tid, u32 buf_size)
491065c0893dSRajkumar Manoharan {
491165c0893dSRajkumar Manoharan 	struct wmi_addba_send_cmd *cmd;
491265c0893dSRajkumar Manoharan 	struct sk_buff *skb;
491365c0893dSRajkumar Manoharan 
491465c0893dSRajkumar Manoharan 	if (!mac)
491565c0893dSRajkumar Manoharan 		return ERR_PTR(-EINVAL);
491665c0893dSRajkumar Manoharan 
491765c0893dSRajkumar Manoharan 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
491865c0893dSRajkumar Manoharan 	if (!skb)
491965c0893dSRajkumar Manoharan 		return ERR_PTR(-ENOMEM);
492065c0893dSRajkumar Manoharan 
492165c0893dSRajkumar Manoharan 	cmd = (struct wmi_addba_send_cmd *)skb->data;
492265c0893dSRajkumar Manoharan 	cmd->vdev_id = __cpu_to_le32(vdev_id);
492365c0893dSRajkumar Manoharan 	ether_addr_copy(cmd->peer_macaddr.addr, mac);
492465c0893dSRajkumar Manoharan 	cmd->tid = __cpu_to_le32(tid);
492565c0893dSRajkumar Manoharan 	cmd->buffersize = __cpu_to_le32(buf_size);
492665c0893dSRajkumar Manoharan 
492765c0893dSRajkumar Manoharan 	ath10k_dbg(ar, ATH10K_DBG_WMI,
492865c0893dSRajkumar Manoharan 		   "wmi addba send vdev_id 0x%X mac_addr %pM tid %u bufsize %u\n",
492965c0893dSRajkumar Manoharan 		   vdev_id, mac, tid, buf_size);
493065c0893dSRajkumar Manoharan 	return skb;
493165c0893dSRajkumar Manoharan }
493265c0893dSRajkumar Manoharan 
493311597413SRajkumar Manoharan static struct sk_buff *
493411597413SRajkumar Manoharan ath10k_wmi_op_gen_addba_set_resp(struct ath10k *ar, u32 vdev_id, const u8 *mac,
493511597413SRajkumar Manoharan 				 u32 tid, u32 status)
493611597413SRajkumar Manoharan {
493711597413SRajkumar Manoharan 	struct wmi_addba_setresponse_cmd *cmd;
493811597413SRajkumar Manoharan 	struct sk_buff *skb;
493911597413SRajkumar Manoharan 
494011597413SRajkumar Manoharan 	if (!mac)
494111597413SRajkumar Manoharan 		return ERR_PTR(-EINVAL);
494211597413SRajkumar Manoharan 
494311597413SRajkumar Manoharan 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
494411597413SRajkumar Manoharan 	if (!skb)
494511597413SRajkumar Manoharan 		return ERR_PTR(-ENOMEM);
494611597413SRajkumar Manoharan 
494711597413SRajkumar Manoharan 	cmd = (struct wmi_addba_setresponse_cmd *)skb->data;
494811597413SRajkumar Manoharan 	cmd->vdev_id = __cpu_to_le32(vdev_id);
494911597413SRajkumar Manoharan 	ether_addr_copy(cmd->peer_macaddr.addr, mac);
495011597413SRajkumar Manoharan 	cmd->tid = __cpu_to_le32(tid);
495111597413SRajkumar Manoharan 	cmd->statuscode = __cpu_to_le32(status);
495211597413SRajkumar Manoharan 
495311597413SRajkumar Manoharan 	ath10k_dbg(ar, ATH10K_DBG_WMI,
495411597413SRajkumar Manoharan 		   "wmi addba set resp vdev_id 0x%X mac_addr %pM tid %u status %u\n",
495511597413SRajkumar Manoharan 		   vdev_id, mac, tid, status);
495611597413SRajkumar Manoharan 	return skb;
495711597413SRajkumar Manoharan }
495811597413SRajkumar Manoharan 
495950abef85SRajkumar Manoharan static struct sk_buff *
496050abef85SRajkumar Manoharan ath10k_wmi_op_gen_delba_send(struct ath10k *ar, u32 vdev_id, const u8 *mac,
496150abef85SRajkumar Manoharan 			     u32 tid, u32 initiator, u32 reason)
496250abef85SRajkumar Manoharan {
496350abef85SRajkumar Manoharan 	struct wmi_delba_send_cmd *cmd;
496450abef85SRajkumar Manoharan 	struct sk_buff *skb;
496550abef85SRajkumar Manoharan 
496650abef85SRajkumar Manoharan 	if (!mac)
496750abef85SRajkumar Manoharan 		return ERR_PTR(-EINVAL);
496850abef85SRajkumar Manoharan 
496950abef85SRajkumar Manoharan 	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
497050abef85SRajkumar Manoharan 	if (!skb)
497150abef85SRajkumar Manoharan 		return ERR_PTR(-ENOMEM);
497250abef85SRajkumar Manoharan 
497350abef85SRajkumar Manoharan 	cmd = (struct wmi_delba_send_cmd *)skb->data;
497450abef85SRajkumar Manoharan 	cmd->vdev_id = __cpu_to_le32(vdev_id);
497550abef85SRajkumar Manoharan 	ether_addr_copy(cmd->peer_macaddr.addr, mac);
497650abef85SRajkumar Manoharan 	cmd->tid = __cpu_to_le32(tid);
497750abef85SRajkumar Manoharan 	cmd->initiator = __cpu_to_le32(initiator);
497850abef85SRajkumar Manoharan 	cmd->reasoncode = __cpu_to_le32(reason);
497950abef85SRajkumar Manoharan 
498050abef85SRajkumar Manoharan 	ath10k_dbg(ar, ATH10K_DBG_WMI,
498150abef85SRajkumar Manoharan 		   "wmi delba send vdev_id 0x%X mac_addr %pM tid %u initiator %u reason %u\n",
498250abef85SRajkumar Manoharan 		   vdev_id, mac, tid, initiator, reason);
498350abef85SRajkumar Manoharan 	return skb;
498450abef85SRajkumar Manoharan }
498550abef85SRajkumar Manoharan 
4986d7579d12SMichal Kazior static const struct wmi_ops wmi_ops = {
4987d7579d12SMichal Kazior 	.rx = ath10k_wmi_op_rx,
4988d7579d12SMichal Kazior 	.map_svc = wmi_main_svc_map,
4989d7579d12SMichal Kazior 
4990d7579d12SMichal Kazior 	.pull_scan = ath10k_wmi_op_pull_scan_ev,
4991d7579d12SMichal Kazior 	.pull_mgmt_rx = ath10k_wmi_op_pull_mgmt_rx_ev,
4992d7579d12SMichal Kazior 	.pull_ch_info = ath10k_wmi_op_pull_ch_info_ev,
4993d7579d12SMichal Kazior 	.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
4994d7579d12SMichal Kazior 	.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
4995d7579d12SMichal Kazior 	.pull_swba = ath10k_wmi_op_pull_swba_ev,
4996d7579d12SMichal Kazior 	.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
4997d7579d12SMichal Kazior 	.pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev,
4998d7579d12SMichal Kazior 	.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
4999d7579d12SMichal Kazior 	.pull_fw_stats = ath10k_wmi_main_op_pull_fw_stats,
5000d7579d12SMichal Kazior 
5001d7579d12SMichal Kazior 	.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
5002d7579d12SMichal Kazior 	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
5003d7579d12SMichal Kazior 	.gen_pdev_set_rd = ath10k_wmi_op_gen_pdev_set_rd,
5004d7579d12SMichal Kazior 	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
5005d7579d12SMichal Kazior 	.gen_init = ath10k_wmi_op_gen_init,
5006d7579d12SMichal Kazior 	.gen_start_scan = ath10k_wmi_op_gen_start_scan,
5007d7579d12SMichal Kazior 	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
5008d7579d12SMichal Kazior 	.gen_vdev_create = ath10k_wmi_op_gen_vdev_create,
5009d7579d12SMichal Kazior 	.gen_vdev_delete = ath10k_wmi_op_gen_vdev_delete,
5010d7579d12SMichal Kazior 	.gen_vdev_start = ath10k_wmi_op_gen_vdev_start,
5011d7579d12SMichal Kazior 	.gen_vdev_stop = ath10k_wmi_op_gen_vdev_stop,
5012d7579d12SMichal Kazior 	.gen_vdev_up = ath10k_wmi_op_gen_vdev_up,
5013d7579d12SMichal Kazior 	.gen_vdev_down = ath10k_wmi_op_gen_vdev_down,
5014d7579d12SMichal Kazior 	.gen_vdev_set_param = ath10k_wmi_op_gen_vdev_set_param,
5015d7579d12SMichal Kazior 	.gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key,
5016d7579d12SMichal Kazior 	.gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf,
5017d7579d12SMichal Kazior 	.gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable,
5018d7579d12SMichal Kazior 	.gen_peer_create = ath10k_wmi_op_gen_peer_create,
5019d7579d12SMichal Kazior 	.gen_peer_delete = ath10k_wmi_op_gen_peer_delete,
5020d7579d12SMichal Kazior 	.gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
5021d7579d12SMichal Kazior 	.gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param,
5022d7579d12SMichal Kazior 	.gen_peer_assoc = ath10k_wmi_op_gen_peer_assoc,
5023d7579d12SMichal Kazior 	.gen_set_psmode = ath10k_wmi_op_gen_set_psmode,
5024d7579d12SMichal Kazior 	.gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps,
5025d7579d12SMichal Kazior 	.gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps,
5026d7579d12SMichal Kazior 	.gen_scan_chan_list = ath10k_wmi_op_gen_scan_chan_list,
5027d7579d12SMichal Kazior 	.gen_beacon_dma = ath10k_wmi_op_gen_beacon_dma,
5028d7579d12SMichal Kazior 	.gen_pdev_set_wmm = ath10k_wmi_op_gen_pdev_set_wmm,
5029d7579d12SMichal Kazior 	.gen_request_stats = ath10k_wmi_op_gen_request_stats,
5030d7579d12SMichal Kazior 	.gen_force_fw_hang = ath10k_wmi_op_gen_force_fw_hang,
5031d7579d12SMichal Kazior 	.gen_mgmt_tx = ath10k_wmi_op_gen_mgmt_tx,
5032d7579d12SMichal Kazior 	.gen_dbglog_cfg = ath10k_wmi_op_gen_dbglog_cfg,
5033d7579d12SMichal Kazior 	.gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable,
5034d7579d12SMichal Kazior 	.gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable,
5035ffdd738dSRajkumar Manoharan 	.gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode,
5036a57a6a27SRajkumar Manoharan 	/* .gen_pdev_get_temperature not implemented */
5037dc8ab278SRajkumar Manoharan 	.gen_addba_clear_resp = ath10k_wmi_op_gen_addba_clear_resp,
503865c0893dSRajkumar Manoharan 	.gen_addba_send = ath10k_wmi_op_gen_addba_send,
503911597413SRajkumar Manoharan 	.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
504050abef85SRajkumar Manoharan 	.gen_delba_send = ath10k_wmi_op_gen_delba_send,
5041be9ce9d8SMichal Kazior 	/* .gen_bcn_tmpl not implemented */
5042d7579d12SMichal Kazior };
5043d7579d12SMichal Kazior 
5044d7579d12SMichal Kazior static const struct wmi_ops wmi_10_1_ops = {
5045d7579d12SMichal Kazior 	.rx = ath10k_wmi_10_1_op_rx,
5046d7579d12SMichal Kazior 	.map_svc = wmi_10x_svc_map,
5047d7579d12SMichal Kazior 	.pull_svc_rdy = ath10k_wmi_10x_op_pull_svc_rdy_ev,
5048d7579d12SMichal Kazior 	.pull_fw_stats = ath10k_wmi_10x_op_pull_fw_stats,
5049d7579d12SMichal Kazior 	.gen_init = ath10k_wmi_10_1_op_gen_init,
5050d7579d12SMichal Kazior 	.gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd,
5051d7579d12SMichal Kazior 	.gen_start_scan = ath10k_wmi_10x_op_gen_start_scan,
5052d7579d12SMichal Kazior 	.gen_peer_assoc = ath10k_wmi_10_1_op_gen_peer_assoc,
5053a57a6a27SRajkumar Manoharan 	/* .gen_pdev_get_temperature not implemented */
5054d7579d12SMichal Kazior 
5055d7579d12SMichal Kazior 	/* shared with main branch */
5056d7579d12SMichal Kazior 	.pull_scan = ath10k_wmi_op_pull_scan_ev,
5057d7579d12SMichal Kazior 	.pull_mgmt_rx = ath10k_wmi_op_pull_mgmt_rx_ev,
5058d7579d12SMichal Kazior 	.pull_ch_info = ath10k_wmi_op_pull_ch_info_ev,
5059d7579d12SMichal Kazior 	.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
5060d7579d12SMichal Kazior 	.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
5061d7579d12SMichal Kazior 	.pull_swba = ath10k_wmi_op_pull_swba_ev,
5062d7579d12SMichal Kazior 	.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
5063d7579d12SMichal Kazior 	.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
5064d7579d12SMichal Kazior 
5065d7579d12SMichal Kazior 	.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
5066d7579d12SMichal Kazior 	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
5067d7579d12SMichal Kazior 	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
5068d7579d12SMichal Kazior 	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
5069d7579d12SMichal Kazior 	.gen_vdev_create = ath10k_wmi_op_gen_vdev_create,
5070d7579d12SMichal Kazior 	.gen_vdev_delete = ath10k_wmi_op_gen_vdev_delete,
5071d7579d12SMichal Kazior 	.gen_vdev_start = ath10k_wmi_op_gen_vdev_start,
5072d7579d12SMichal Kazior 	.gen_vdev_stop = ath10k_wmi_op_gen_vdev_stop,
5073d7579d12SMichal Kazior 	.gen_vdev_up = ath10k_wmi_op_gen_vdev_up,
5074d7579d12SMichal Kazior 	.gen_vdev_down = ath10k_wmi_op_gen_vdev_down,
5075d7579d12SMichal Kazior 	.gen_vdev_set_param = ath10k_wmi_op_gen_vdev_set_param,
5076d7579d12SMichal Kazior 	.gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key,
5077d7579d12SMichal Kazior 	.gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf,
5078d7579d12SMichal Kazior 	.gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable,
5079d7579d12SMichal Kazior 	.gen_peer_create = ath10k_wmi_op_gen_peer_create,
5080d7579d12SMichal Kazior 	.gen_peer_delete = ath10k_wmi_op_gen_peer_delete,
5081d7579d12SMichal Kazior 	.gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
5082d7579d12SMichal Kazior 	.gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param,
5083d7579d12SMichal Kazior 	.gen_set_psmode = ath10k_wmi_op_gen_set_psmode,
5084d7579d12SMichal Kazior 	.gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps,
5085d7579d12SMichal Kazior 	.gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps,
5086d7579d12SMichal Kazior 	.gen_scan_chan_list = ath10k_wmi_op_gen_scan_chan_list,
5087d7579d12SMichal Kazior 	.gen_beacon_dma = ath10k_wmi_op_gen_beacon_dma,
5088d7579d12SMichal Kazior 	.gen_pdev_set_wmm = ath10k_wmi_op_gen_pdev_set_wmm,
5089d7579d12SMichal Kazior 	.gen_request_stats = ath10k_wmi_op_gen_request_stats,
5090d7579d12SMichal Kazior 	.gen_force_fw_hang = ath10k_wmi_op_gen_force_fw_hang,
5091d7579d12SMichal Kazior 	.gen_mgmt_tx = ath10k_wmi_op_gen_mgmt_tx,
5092d7579d12SMichal Kazior 	.gen_dbglog_cfg = ath10k_wmi_op_gen_dbglog_cfg,
5093d7579d12SMichal Kazior 	.gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable,
5094d7579d12SMichal Kazior 	.gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable,
5095ffdd738dSRajkumar Manoharan 	.gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode,
5096dc8ab278SRajkumar Manoharan 	.gen_addba_clear_resp = ath10k_wmi_op_gen_addba_clear_resp,
509765c0893dSRajkumar Manoharan 	.gen_addba_send = ath10k_wmi_op_gen_addba_send,
509811597413SRajkumar Manoharan 	.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
509950abef85SRajkumar Manoharan 	.gen_delba_send = ath10k_wmi_op_gen_delba_send,
5100be9ce9d8SMichal Kazior 	/* .gen_bcn_tmpl not implemented */
5101d7579d12SMichal Kazior };
5102d7579d12SMichal Kazior 
5103d7579d12SMichal Kazior static const struct wmi_ops wmi_10_2_ops = {
5104d7579d12SMichal Kazior 	.rx = ath10k_wmi_10_2_op_rx,
5105d7579d12SMichal Kazior 	.gen_init = ath10k_wmi_10_2_op_gen_init,
5106d7579d12SMichal Kazior 	.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
5107a57a6a27SRajkumar Manoharan 	/* .gen_pdev_get_temperature not implemented */
5108d7579d12SMichal Kazior 
5109d7579d12SMichal Kazior 	/* shared with 10.1 */
5110d7579d12SMichal Kazior 	.map_svc = wmi_10x_svc_map,
5111d7579d12SMichal Kazior 	.pull_svc_rdy = ath10k_wmi_10x_op_pull_svc_rdy_ev,
5112d7579d12SMichal Kazior 	.pull_fw_stats = ath10k_wmi_10x_op_pull_fw_stats,
5113d7579d12SMichal Kazior 	.gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd,
5114d7579d12SMichal Kazior 	.gen_start_scan = ath10k_wmi_10x_op_gen_start_scan,
5115d7579d12SMichal Kazior 
5116d7579d12SMichal Kazior 	.pull_scan = ath10k_wmi_op_pull_scan_ev,
5117d7579d12SMichal Kazior 	.pull_mgmt_rx = ath10k_wmi_op_pull_mgmt_rx_ev,
5118d7579d12SMichal Kazior 	.pull_ch_info = ath10k_wmi_op_pull_ch_info_ev,
5119d7579d12SMichal Kazior 	.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
5120d7579d12SMichal Kazior 	.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
5121d7579d12SMichal Kazior 	.pull_swba = ath10k_wmi_op_pull_swba_ev,
5122d7579d12SMichal Kazior 	.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
5123d7579d12SMichal Kazior 	.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
5124d7579d12SMichal Kazior 
5125d7579d12SMichal Kazior 	.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
5126d7579d12SMichal Kazior 	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
5127d7579d12SMichal Kazior 	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
5128d7579d12SMichal Kazior 	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
5129d7579d12SMichal Kazior 	.gen_vdev_create = ath10k_wmi_op_gen_vdev_create,
5130d7579d12SMichal Kazior 	.gen_vdev_delete = ath10k_wmi_op_gen_vdev_delete,
5131d7579d12SMichal Kazior 	.gen_vdev_start = ath10k_wmi_op_gen_vdev_start,
5132d7579d12SMichal Kazior 	.gen_vdev_stop = ath10k_wmi_op_gen_vdev_stop,
5133d7579d12SMichal Kazior 	.gen_vdev_up = ath10k_wmi_op_gen_vdev_up,
5134d7579d12SMichal Kazior 	.gen_vdev_down = ath10k_wmi_op_gen_vdev_down,
5135d7579d12SMichal Kazior 	.gen_vdev_set_param = ath10k_wmi_op_gen_vdev_set_param,
5136d7579d12SMichal Kazior 	.gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key,
5137d7579d12SMichal Kazior 	.gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf,
5138d7579d12SMichal Kazior 	.gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable,
5139d7579d12SMichal Kazior 	.gen_peer_create = ath10k_wmi_op_gen_peer_create,
5140d7579d12SMichal Kazior 	.gen_peer_delete = ath10k_wmi_op_gen_peer_delete,
5141d7579d12SMichal Kazior 	.gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
5142d7579d12SMichal Kazior 	.gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param,
5143d7579d12SMichal Kazior 	.gen_set_psmode = ath10k_wmi_op_gen_set_psmode,
5144d7579d12SMichal Kazior 	.gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps,
5145d7579d12SMichal Kazior 	.gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps,
5146d7579d12SMichal Kazior 	.gen_scan_chan_list = ath10k_wmi_op_gen_scan_chan_list,
5147d7579d12SMichal Kazior 	.gen_beacon_dma = ath10k_wmi_op_gen_beacon_dma,
5148d7579d12SMichal Kazior 	.gen_pdev_set_wmm = ath10k_wmi_op_gen_pdev_set_wmm,
5149d7579d12SMichal Kazior 	.gen_request_stats = ath10k_wmi_op_gen_request_stats,
5150d7579d12SMichal Kazior 	.gen_force_fw_hang = ath10k_wmi_op_gen_force_fw_hang,
5151d7579d12SMichal Kazior 	.gen_mgmt_tx = ath10k_wmi_op_gen_mgmt_tx,
5152d7579d12SMichal Kazior 	.gen_dbglog_cfg = ath10k_wmi_op_gen_dbglog_cfg,
5153d7579d12SMichal Kazior 	.gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable,
5154d7579d12SMichal Kazior 	.gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable,
5155ffdd738dSRajkumar Manoharan 	.gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode,
5156dc8ab278SRajkumar Manoharan 	.gen_addba_clear_resp = ath10k_wmi_op_gen_addba_clear_resp,
515765c0893dSRajkumar Manoharan 	.gen_addba_send = ath10k_wmi_op_gen_addba_send,
515811597413SRajkumar Manoharan 	.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
515950abef85SRajkumar Manoharan 	.gen_delba_send = ath10k_wmi_op_gen_delba_send,
5160d7579d12SMichal Kazior };
5161d7579d12SMichal Kazior 
51624a16fbecSRajkumar Manoharan static const struct wmi_ops wmi_10_2_4_ops = {
51634a16fbecSRajkumar Manoharan 	.rx = ath10k_wmi_10_2_op_rx,
51644a16fbecSRajkumar Manoharan 	.gen_init = ath10k_wmi_10_2_op_gen_init,
51654a16fbecSRajkumar Manoharan 	.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
5166a57a6a27SRajkumar Manoharan 	.gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature,
51674a16fbecSRajkumar Manoharan 
51684a16fbecSRajkumar Manoharan 	/* shared with 10.1 */
51694a16fbecSRajkumar Manoharan 	.map_svc = wmi_10x_svc_map,
51704a16fbecSRajkumar Manoharan 	.pull_svc_rdy = ath10k_wmi_10x_op_pull_svc_rdy_ev,
51714a16fbecSRajkumar Manoharan 	.pull_fw_stats = ath10k_wmi_10x_op_pull_fw_stats,
51724a16fbecSRajkumar Manoharan 	.gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd,
51734a16fbecSRajkumar Manoharan 	.gen_start_scan = ath10k_wmi_10x_op_gen_start_scan,
51744a16fbecSRajkumar Manoharan 
51754a16fbecSRajkumar Manoharan 	.pull_scan = ath10k_wmi_op_pull_scan_ev,
51764a16fbecSRajkumar Manoharan 	.pull_mgmt_rx = ath10k_wmi_op_pull_mgmt_rx_ev,
51774a16fbecSRajkumar Manoharan 	.pull_ch_info = ath10k_wmi_op_pull_ch_info_ev,
51784a16fbecSRajkumar Manoharan 	.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
51794a16fbecSRajkumar Manoharan 	.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
51804a16fbecSRajkumar Manoharan 	.pull_swba = ath10k_wmi_op_pull_swba_ev,
51814a16fbecSRajkumar Manoharan 	.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
51824a16fbecSRajkumar Manoharan 	.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
51834a16fbecSRajkumar Manoharan 
51844a16fbecSRajkumar Manoharan 	.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
51854a16fbecSRajkumar Manoharan 	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
51864a16fbecSRajkumar Manoharan 	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
51874a16fbecSRajkumar Manoharan 	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
51884a16fbecSRajkumar Manoharan 	.gen_vdev_create = ath10k_wmi_op_gen_vdev_create,
51894a16fbecSRajkumar Manoharan 	.gen_vdev_delete = ath10k_wmi_op_gen_vdev_delete,
51904a16fbecSRajkumar Manoharan 	.gen_vdev_start = ath10k_wmi_op_gen_vdev_start,
51914a16fbecSRajkumar Manoharan 	.gen_vdev_stop = ath10k_wmi_op_gen_vdev_stop,
51924a16fbecSRajkumar Manoharan 	.gen_vdev_up = ath10k_wmi_op_gen_vdev_up,
51934a16fbecSRajkumar Manoharan 	.gen_vdev_down = ath10k_wmi_op_gen_vdev_down,
51944a16fbecSRajkumar Manoharan 	.gen_vdev_set_param = ath10k_wmi_op_gen_vdev_set_param,
51954a16fbecSRajkumar Manoharan 	.gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key,
51964a16fbecSRajkumar Manoharan 	.gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf,
51974a16fbecSRajkumar Manoharan 	.gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable,
51984a16fbecSRajkumar Manoharan 	.gen_peer_create = ath10k_wmi_op_gen_peer_create,
51994a16fbecSRajkumar Manoharan 	.gen_peer_delete = ath10k_wmi_op_gen_peer_delete,
52004a16fbecSRajkumar Manoharan 	.gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
52014a16fbecSRajkumar Manoharan 	.gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param,
52024a16fbecSRajkumar Manoharan 	.gen_set_psmode = ath10k_wmi_op_gen_set_psmode,
52034a16fbecSRajkumar Manoharan 	.gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps,
52044a16fbecSRajkumar Manoharan 	.gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps,
52054a16fbecSRajkumar Manoharan 	.gen_scan_chan_list = ath10k_wmi_op_gen_scan_chan_list,
52064a16fbecSRajkumar Manoharan 	.gen_beacon_dma = ath10k_wmi_op_gen_beacon_dma,
52074a16fbecSRajkumar Manoharan 	.gen_pdev_set_wmm = ath10k_wmi_op_gen_pdev_set_wmm,
52084a16fbecSRajkumar Manoharan 	.gen_request_stats = ath10k_wmi_op_gen_request_stats,
52094a16fbecSRajkumar Manoharan 	.gen_force_fw_hang = ath10k_wmi_op_gen_force_fw_hang,
52104a16fbecSRajkumar Manoharan 	.gen_mgmt_tx = ath10k_wmi_op_gen_mgmt_tx,
52114a16fbecSRajkumar Manoharan 	.gen_dbglog_cfg = ath10k_wmi_op_gen_dbglog_cfg,
52124a16fbecSRajkumar Manoharan 	.gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable,
52134a16fbecSRajkumar Manoharan 	.gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable,
5214ffdd738dSRajkumar Manoharan 	.gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode,
5215dc8ab278SRajkumar Manoharan 	.gen_addba_clear_resp = ath10k_wmi_op_gen_addba_clear_resp,
521665c0893dSRajkumar Manoharan 	.gen_addba_send = ath10k_wmi_op_gen_addba_send,
521711597413SRajkumar Manoharan 	.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
521850abef85SRajkumar Manoharan 	.gen_delba_send = ath10k_wmi_op_gen_delba_send,
5219be9ce9d8SMichal Kazior 	/* .gen_bcn_tmpl not implemented */
52204a16fbecSRajkumar Manoharan };
52214a16fbecSRajkumar Manoharan 
5222b79b9baaSMichal Kazior int ath10k_wmi_attach(struct ath10k *ar)
5223b79b9baaSMichal Kazior {
5224d7579d12SMichal Kazior 	switch (ar->wmi.op_version) {
52254a16fbecSRajkumar Manoharan 	case ATH10K_FW_WMI_OP_VERSION_10_2_4:
52264a16fbecSRajkumar Manoharan 		ar->wmi.cmd = &wmi_10_2_4_cmd_map;
52274a16fbecSRajkumar Manoharan 		ar->wmi.ops = &wmi_10_2_4_ops;
52284a16fbecSRajkumar Manoharan 		ar->wmi.vdev_param = &wmi_10_2_4_vdev_param_map;
52294a16fbecSRajkumar Manoharan 		ar->wmi.pdev_param = &wmi_10_2_4_pdev_param_map;
52304a16fbecSRajkumar Manoharan 		break;
5231d7579d12SMichal Kazior 	case ATH10K_FW_WMI_OP_VERSION_10_2:
5232b79b9baaSMichal Kazior 		ar->wmi.cmd = &wmi_10_2_cmd_map;
5233d7579d12SMichal Kazior 		ar->wmi.ops = &wmi_10_2_ops;
5234b79b9baaSMichal Kazior 		ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
5235b79b9baaSMichal Kazior 		ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
5236d7579d12SMichal Kazior 		break;
5237d7579d12SMichal Kazior 	case ATH10K_FW_WMI_OP_VERSION_10_1:
5238d7579d12SMichal Kazior 		ar->wmi.cmd = &wmi_10x_cmd_map;
5239d7579d12SMichal Kazior 		ar->wmi.ops = &wmi_10_1_ops;
5240d7579d12SMichal Kazior 		ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
5241d7579d12SMichal Kazior 		ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
5242d7579d12SMichal Kazior 		break;
5243d7579d12SMichal Kazior 	case ATH10K_FW_WMI_OP_VERSION_MAIN:
5244b79b9baaSMichal Kazior 		ar->wmi.cmd = &wmi_cmd_map;
5245d7579d12SMichal Kazior 		ar->wmi.ops = &wmi_ops;
5246b79b9baaSMichal Kazior 		ar->wmi.vdev_param = &wmi_vdev_param_map;
5247b79b9baaSMichal Kazior 		ar->wmi.pdev_param = &wmi_pdev_param_map;
5248d7579d12SMichal Kazior 		break;
5249ca996ec5SMichal Kazior 	case ATH10K_FW_WMI_OP_VERSION_TLV:
5250ca996ec5SMichal Kazior 		ath10k_wmi_tlv_attach(ar);
5251ca996ec5SMichal Kazior 		break;
5252d7579d12SMichal Kazior 	case ATH10K_FW_WMI_OP_VERSION_UNSET:
5253d7579d12SMichal Kazior 	case ATH10K_FW_WMI_OP_VERSION_MAX:
5254d7579d12SMichal Kazior 		ath10k_err(ar, "unsupported WMI op version: %d\n",
5255d7579d12SMichal Kazior 			   ar->wmi.op_version);
5256d7579d12SMichal Kazior 		return -EINVAL;
5257b79b9baaSMichal Kazior 	}
5258b79b9baaSMichal Kazior 
5259b79b9baaSMichal Kazior 	init_completion(&ar->wmi.service_ready);
5260b79b9baaSMichal Kazior 	init_completion(&ar->wmi.unified_ready);
5261b79b9baaSMichal Kazior 
5262b79b9baaSMichal Kazior 	return 0;
5263b79b9baaSMichal Kazior }
5264b79b9baaSMichal Kazior 
5265b79b9baaSMichal Kazior void ath10k_wmi_detach(struct ath10k *ar)
5266b79b9baaSMichal Kazior {
5267b79b9baaSMichal Kazior 	int i;
5268b79b9baaSMichal Kazior 
5269b79b9baaSMichal Kazior 	/* free the host memory chunks requested by firmware */
5270b79b9baaSMichal Kazior 	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
5271b79b9baaSMichal Kazior 		dma_free_coherent(ar->dev,
5272b79b9baaSMichal Kazior 				  ar->wmi.mem_chunks[i].len,
5273b79b9baaSMichal Kazior 				  ar->wmi.mem_chunks[i].vaddr,
5274b79b9baaSMichal Kazior 				  ar->wmi.mem_chunks[i].paddr);
5275b79b9baaSMichal Kazior 	}
5276b79b9baaSMichal Kazior 
5277b79b9baaSMichal Kazior 	ar->wmi.num_mem_chunks = 0;
5278b79b9baaSMichal Kazior }
5279