xref: /linux/drivers/net/wireless/ath/wcn36xx/smd.c (revision 8f7aa3d3c7323f4ca2768a9e74ebbe359c4f8f88)
1 /*
2  * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18 
19 #include <linux/bitfield.h>
20 #include <linux/etherdevice.h>
21 #include <linux/firmware.h>
22 #include <linux/bitops.h>
23 #include <linux/rpmsg.h>
24 #include "smd.h"
25 #include "firmware.h"
26 
27 struct wcn36xx_cfg_val {
28 	u32 cfg_id;
29 	u32 value;
30 };
31 
32 #define WCN36XX_CFG_VAL(id, val) \
33 { \
34 	.cfg_id = WCN36XX_HAL_CFG_ ## id, \
35 	.value = val \
36 }
37 
38 static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = {
39 	WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
40 	WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
41 	WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0),
42 	WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785),
43 	WCN36XX_CFG_VAL(CAL_PERIOD, 5),
44 	WCN36XX_CFG_VAL(CAL_CONTROL, 1),
45 	WCN36XX_CFG_VAL(PROXIMITY, 0),
46 	WCN36XX_CFG_VAL(NETWORK_DENSITY, 3),
47 	WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 6000),
48 	WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64),
49 	WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347),
50 	WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 15),
51 	WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 15),
52 	WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000),
53 	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5),
54 	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10),
55 	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15),
56 	WCN36XX_CFG_VAL(FIXED_RATE, 0),
57 	WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4),
58 	WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 0),
59 	WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 0),
60 	WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5),
61 	WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1),
62 	WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5),
63 	WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5),
64 	WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40),
65 	WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200),
66 	WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1),
67 	WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1),
68 	WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20),
69 	WCN36XX_CFG_VAL(STATS_PERIOD, 10),
70 	WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000),
71 	WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0),
72 	WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128),
73 	WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560),
74 	WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
75 	WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
76 	WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
77 	WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
78 	WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 120000),
79 	WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000),
80 	WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
81 	WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
82 	WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 133), /* MCS 5 */
83 	WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 1000),
84 };
85 
86 static struct wcn36xx_cfg_val wcn3680_cfg_vals[] = {
87 	WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
88 	WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
89 	WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0),
90 	WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785),
91 	WCN36XX_CFG_VAL(CAL_PERIOD, 5),
92 	WCN36XX_CFG_VAL(CAL_CONTROL, 1),
93 	WCN36XX_CFG_VAL(PROXIMITY, 0),
94 	WCN36XX_CFG_VAL(NETWORK_DENSITY, 3),
95 	WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 4096),
96 	WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64),
97 	WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347),
98 	WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 15),
99 	WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 15),
100 	WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000),
101 	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5),
102 	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10),
103 	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15),
104 	WCN36XX_CFG_VAL(FIXED_RATE, 0),
105 	WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4),
106 	WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 0),
107 	WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 0),
108 	WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5),
109 	WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1),
110 	WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5),
111 	WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_24GHZ, 1),
112 	WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5),
113 	WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40),
114 	WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200),
115 	WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1),
116 	WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1),
117 	WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20),
118 	WCN36XX_CFG_VAL(STATS_PERIOD, 10),
119 	WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000),
120 	WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0),
121 	WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128),
122 	WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560),
123 	WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
124 	WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
125 	WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
126 	WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
127 	WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 120000),
128 	WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000),
129 	WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
130 	WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
131 	WCN36XX_CFG_VAL(TDLS_PUAPSD_MASK, 0),
132 	WCN36XX_CFG_VAL(TDLS_PUAPSD_BUFFER_STA_CAPABLE, 1),
133 	WCN36XX_CFG_VAL(TDLS_PUAPSD_INACTIVITY_TIME, 0),
134 	WCN36XX_CFG_VAL(TDLS_PUAPSD_RX_FRAME_THRESHOLD, 10),
135 	WCN36XX_CFG_VAL(TDLS_OFF_CHANNEL_CAPABLE, 1),
136 	WCN36XX_CFG_VAL(ENABLE_ADAPTIVE_RX_DRAIN, 1),
137 	WCN36XX_CFG_VAL(FLEXCONNECT_POWER_FACTOR, 0),
138 	WCN36XX_CFG_VAL(ANTENNA_DIVERSITY, 3),
139 	WCN36XX_CFG_VAL(ATH_DISABLE, 0),
140 	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_WLAN_LEN, 60000),
141 	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_BT_LEN, 90000),
142 	WCN36XX_CFG_VAL(BTC_SAP_STATIC_OPP_ACTIVE_WLAN_LEN, 30000),
143 	WCN36XX_CFG_VAL(BTC_SAP_STATIC_OPP_ACTIVE_BT_LEN, 30000),
144 	WCN36XX_CFG_VAL(ASD_PROBE_INTERVAL, 50),
145 	WCN36XX_CFG_VAL(ASD_TRIGGER_THRESHOLD, -60),
146 	WCN36XX_CFG_VAL(ASD_RTT_RSSI_HYST_THRESHOLD, 3),
147 	WCN36XX_CFG_VAL(BTC_CTS2S_ON_STA_DURING_SCO, 0),
148 	WCN36XX_CFG_VAL(RA_FILTER_ENABLE, 0),
149 	WCN36XX_CFG_VAL(RA_RATE_LIMIT_INTERVAL, 60),
150 	WCN36XX_CFG_VAL(BTC_FATAL_HID_NSNIFF_BLK, 2),
151 	WCN36XX_CFG_VAL(BTC_CRITICAL_HID_NSNIFF_BLK, 1),
152 	WCN36XX_CFG_VAL(BTC_DYN_A2DP_TX_QUEUE_THOLD, 0),
153 	WCN36XX_CFG_VAL(BTC_DYN_OPP_TX_QUEUE_THOLD, 1),
154 	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_SP, 10),
155 	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_RX_CNT, 50),
156 	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_TX_CNT, 50),
157 	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_TX_CNT_MEAS_WINDOW, 500),
158 	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_RX_CNT_MEAS_WINDOW, 500),
159 	WCN36XX_CFG_VAL(MAX_PSPOLL_IN_WMM_UAPSD_PS_MODE, 0),
160 	WCN36XX_CFG_VAL(MAX_UAPSD_INACTIVITY_INTERVALS, 10),
161 	WCN36XX_CFG_VAL(ENABLE_DYNAMIC_WMMPS, 1),
162 	WCN36XX_CFG_VAL(BURST_MODE_BE_TXOP_VALUE, 0),
163 	WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 136),
164 	WCN36XX_CFG_VAL(BTC_FAST_WLAN_CONN_PREF, 1),
165 	WCN36XX_CFG_VAL(ENABLE_RTSCTS_HTVHT, 0),
166 	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_WLAN_LEN, 30000),
167 	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_BT_LEN, 120000),
168 	WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 1000),
169 	WCN36XX_CFG_VAL(TOGGLE_ARP_BDRATES, 0),
170 	WCN36XX_CFG_VAL(OPTIMIZE_CA_EVENT, 0),
171 	WCN36XX_CFG_VAL(EXT_SCAN_CONC_MODE, 0),
172 	WCN36XX_CFG_VAL(BAR_WAKEUP_HOST_DISABLE, 0),
173 	WCN36XX_CFG_VAL(SAR_BOFFSET_CORRECTION_ENABLE, 0),
174 	WCN36XX_CFG_VAL(BTC_DISABLE_WLAN_LINK_CRITICAL, 5),
175 	WCN36XX_CFG_VAL(DISABLE_SCAN_DURING_SCO, 2),
176 	WCN36XX_CFG_VAL(CONS_BCNMISS_COUNT, 0),
177 	WCN36XX_CFG_VAL(UNITS_OF_BCN_WAIT_TIME, 0),
178 	WCN36XX_CFG_VAL(TRIGGER_NULLFRAME_BEFORE_HB, 0),
179 	WCN36XX_CFG_VAL(ENABLE_POWERSAVE_OFFLOAD, 0),
180 };
181 
182 static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value)
183 {
184 	struct wcn36xx_hal_cfg *entry;
185 	u32 *val;
186 
187 	if (*len + sizeof(*entry) + sizeof(u32) >= WCN36XX_HAL_BUF_SIZE) {
188 		wcn36xx_err("Not enough room for TLV entry\n");
189 		return -ENOMEM;
190 	}
191 
192 	entry = (struct wcn36xx_hal_cfg *) (wcn->hal_buf + *len);
193 	entry->id = id;
194 	entry->len = sizeof(u32);
195 	entry->pad_bytes = 0;
196 	entry->reserve = 0;
197 
198 	val = (u32 *) (entry + 1);
199 	*val = value;
200 
201 	*len += sizeof(*entry) + sizeof(u32);
202 
203 	return 0;
204 }
205 
206 static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn,
207 		struct ieee80211_sta *sta,
208 		struct wcn36xx_hal_config_bss_params *bss_params)
209 {
210 	if (NL80211_BAND_5GHZ == WCN36XX_BAND(wcn))
211 		bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE;
212 	else if (sta && sta->deflink.ht_cap.ht_supported)
213 		bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE;
214 	else if (sta && (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0x7f))
215 		bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE;
216 	else
217 		bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE;
218 }
219 
220 static inline u8 is_cap_supported(unsigned long caps, unsigned long flag)
221 {
222 	return caps & flag ? 1 : 0;
223 }
224 
225 static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif,
226 		struct ieee80211_sta *sta,
227 		struct wcn36xx_hal_config_bss_params *bss_params)
228 {
229 	if (sta && sta->deflink.ht_cap.ht_supported) {
230 		unsigned long caps = sta->deflink.ht_cap.cap;
231 
232 		bss_params->ht = sta->deflink.ht_cap.ht_supported;
233 		bss_params->tx_channel_width_set = is_cap_supported(caps,
234 			IEEE80211_HT_CAP_SUP_WIDTH_20_40);
235 		bss_params->lsig_tx_op_protection_full_support =
236 			is_cap_supported(caps,
237 					 IEEE80211_HT_CAP_LSIG_TXOP_PROT);
238 
239 		bss_params->ht_oper_mode = vif->bss_conf.ht_operation_mode;
240 		bss_params->lln_non_gf_coexist =
241 			!!(vif->bss_conf.ht_operation_mode &
242 			   IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
243 		/* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */
244 		bss_params->dual_cts_protection = 0;
245 		/* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */
246 		bss_params->ht20_coexist = 0;
247 	}
248 }
249 
250 static void
251 wcn36xx_smd_set_bss_vht_params(struct ieee80211_vif *vif,
252 			       struct ieee80211_sta *sta,
253 			       struct wcn36xx_hal_config_bss_params_v1 *bss)
254 {
255 	if (sta && sta->deflink.vht_cap.vht_supported)
256 		bss->vht_capable = 1;
257 }
258 
259 static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta,
260 		struct wcn36xx_hal_config_sta_params *sta_params)
261 {
262 	if (sta->deflink.ht_cap.ht_supported) {
263 		unsigned long caps = sta->deflink.ht_cap.cap;
264 
265 		sta_params->ht_capable = sta->deflink.ht_cap.ht_supported;
266 		sta_params->tx_channel_width_set = is_cap_supported(caps,
267 			IEEE80211_HT_CAP_SUP_WIDTH_20_40);
268 		sta_params->lsig_txop_protection = is_cap_supported(caps,
269 			IEEE80211_HT_CAP_LSIG_TXOP_PROT);
270 
271 		sta_params->max_ampdu_size = sta->deflink.ht_cap.ampdu_factor;
272 		sta_params->max_ampdu_density = sta->deflink.ht_cap.ampdu_density;
273 		/* max_amsdu_size: 1 : 3839 bytes, 0 : 7935 bytes (max) */
274 		sta_params->max_amsdu_size = !is_cap_supported(caps,
275 			IEEE80211_HT_CAP_MAX_AMSDU);
276 		sta_params->sgi_20Mhz = is_cap_supported(caps,
277 			IEEE80211_HT_CAP_SGI_20);
278 		sta_params->sgi_40mhz =	is_cap_supported(caps,
279 			IEEE80211_HT_CAP_SGI_40);
280 		sta_params->green_field_capable = is_cap_supported(caps,
281 			IEEE80211_HT_CAP_GRN_FLD);
282 		sta_params->delayed_ba_support = is_cap_supported(caps,
283 			IEEE80211_HT_CAP_DELAY_BA);
284 		sta_params->dsss_cck_mode_40mhz = is_cap_supported(caps,
285 			IEEE80211_HT_CAP_DSSSCCK40);
286 	}
287 }
288 
289 static void wcn36xx_smd_set_sta_vht_params(struct wcn36xx *wcn,
290 		struct ieee80211_sta *sta,
291 		struct wcn36xx_hal_config_sta_params_v1 *sta_params)
292 {
293 	if (sta->deflink.vht_cap.vht_supported) {
294 		unsigned long caps = sta->deflink.vht_cap.cap;
295 
296 		sta_params->vht_capable = sta->deflink.vht_cap.vht_supported;
297 		sta_params->vht_ldpc_enabled =
298 			is_cap_supported(caps, IEEE80211_VHT_CAP_RXLDPC);
299 		if (wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, MU_MIMO)) {
300 			sta_params->vht_tx_mu_beamformee_capable =
301 				is_cap_supported(caps, IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
302 			if (sta_params->vht_tx_mu_beamformee_capable)
303 			       sta_params->vht_tx_bf_enabled = 1;
304 		} else {
305 			sta_params->vht_tx_mu_beamformee_capable = 0;
306 		}
307 		sta_params->vht_tx_channel_width_set = 0;
308 	}
309 }
310 
311 static void wcn36xx_smd_set_sta_ht_ldpc_params(struct ieee80211_sta *sta,
312 		struct wcn36xx_hal_config_sta_params_v1 *sta_params)
313 {
314 	if (sta->deflink.ht_cap.ht_supported) {
315 		sta_params->ht_ldpc_enabled =
316 			is_cap_supported(sta->deflink.ht_cap.cap,
317 					 IEEE80211_HT_CAP_LDPC_CODING);
318 	}
319 }
320 
321 static void wcn36xx_smd_set_sta_default_ht_params(
322 		struct wcn36xx_hal_config_sta_params *sta_params)
323 {
324 	sta_params->ht_capable = 1;
325 	sta_params->tx_channel_width_set = 1;
326 	sta_params->lsig_txop_protection = 1;
327 	sta_params->max_ampdu_size = 3;
328 	sta_params->max_ampdu_density = 5;
329 	sta_params->max_amsdu_size = 0;
330 	sta_params->sgi_20Mhz = 1;
331 	sta_params->sgi_40mhz = 1;
332 	sta_params->green_field_capable = 1;
333 	sta_params->delayed_ba_support = 0;
334 	sta_params->dsss_cck_mode_40mhz = 1;
335 }
336 
337 static void wcn36xx_smd_set_sta_default_vht_params(struct wcn36xx *wcn,
338 		struct wcn36xx_hal_config_sta_params_v1 *sta_params)
339 {
340 	if (wcn->rf_id == RF_IRIS_WCN3680) {
341 		sta_params->vht_capable = 1;
342 		sta_params->vht_tx_mu_beamformee_capable = 1;
343 	} else {
344 		sta_params->vht_capable = 0;
345 		sta_params->vht_tx_mu_beamformee_capable = 0;
346 	}
347 
348 	sta_params->vht_ldpc_enabled = 0;
349 	sta_params->vht_tx_channel_width_set = 0;
350 	sta_params->vht_tx_bf_enabled = 0;
351 }
352 
353 static void wcn36xx_smd_set_sta_default_ht_ldpc_params(struct wcn36xx *wcn,
354 		struct wcn36xx_hal_config_sta_params_v1 *sta_params)
355 {
356 	if (wcn->rf_id == RF_IRIS_WCN3680)
357 		sta_params->ht_ldpc_enabled = 1;
358 	else
359 		sta_params->ht_ldpc_enabled = 0;
360 }
361 
362 static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
363 		struct ieee80211_vif *vif,
364 		struct ieee80211_sta *sta,
365 		struct wcn36xx_hal_config_sta_params *sta_params)
366 {
367 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
368 	struct wcn36xx_sta *sta_priv = NULL;
369 	if (vif->type == NL80211_IFTYPE_ADHOC ||
370 	    vif->type == NL80211_IFTYPE_AP ||
371 	    vif->type == NL80211_IFTYPE_MESH_POINT) {
372 		sta_params->type = 1;
373 		sta_params->sta_index = WCN36XX_HAL_STA_INVALID_IDX;
374 	} else {
375 		sta_params->type = 0;
376 		sta_params->sta_index = vif_priv->self_sta_index;
377 	}
378 
379 	sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
380 
381 	/*
382 	 * In STA mode ieee80211_sta contains bssid and ieee80211_vif
383 	 * contains our mac address. In  AP mode we are bssid so vif
384 	 * contains bssid and ieee80211_sta contains mac.
385 	 */
386 	if (NL80211_IFTYPE_STATION == vif->type)
387 		memcpy(&sta_params->mac, vif->addr, ETH_ALEN);
388 	else
389 		memcpy(&sta_params->bssid, vif->addr, ETH_ALEN);
390 
391 	sta_params->encrypt_type = vif_priv->encrypt_type;
392 	sta_params->short_preamble_supported = true;
393 
394 	sta_params->rifs_mode = 0;
395 	sta_params->rmf = 0;
396 	sta_params->action = 0;
397 	sta_params->uapsd = 0;
398 	sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC;
399 	sta_params->max_ampdu_duration = 0;
400 	sta_params->bssid_index = vif_priv->bss_index;
401 	sta_params->p2p = 0;
402 
403 	if (sta) {
404 		sta_priv = wcn36xx_sta_to_priv(sta);
405 		if (NL80211_IFTYPE_STATION == vif->type)
406 			memcpy(&sta_params->bssid, sta->addr, ETH_ALEN);
407 		else
408 			memcpy(&sta_params->mac, sta->addr, ETH_ALEN);
409 		sta_params->wmm_enabled = sta->wme;
410 		sta_params->max_sp_len = sta->max_sp;
411 		sta_params->aid = sta_priv->aid;
412 		wcn36xx_smd_set_sta_ht_params(sta, sta_params);
413 		memcpy(&sta_params->supported_rates, &sta_priv->supported_rates,
414 			sizeof(struct wcn36xx_hal_supported_rates));
415 	} else {
416 		wcn36xx_set_default_rates((struct wcn36xx_hal_supported_rates *)
417 					  &sta_params->supported_rates);
418 		wcn36xx_smd_set_sta_default_ht_params(sta_params);
419 	}
420 }
421 
422 static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
423 {
424 	int ret;
425 	unsigned long start;
426 	struct wcn36xx_hal_msg_header *hdr =
427 		(struct wcn36xx_hal_msg_header *)wcn->hal_buf;
428 	u16 req_type = hdr->msg_type;
429 
430 	wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len);
431 
432 	init_completion(&wcn->hal_rsp_compl);
433 	start = jiffies;
434 	ret = rpmsg_send(wcn->smd_channel, wcn->hal_buf, len);
435 	if (ret) {
436 		wcn36xx_err("HAL TX failed for req %d\n", req_type);
437 		goto out;
438 	}
439 	if (wait_for_completion_timeout(&wcn->hal_rsp_compl,
440 		msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) {
441 		wcn36xx_err("Timeout! No SMD response to req %d in %dms\n",
442 			    req_type, HAL_MSG_TIMEOUT);
443 		ret = -ETIME;
444 		goto out;
445 	}
446 	wcn36xx_dbg(WCN36XX_DBG_SMD,
447 		    "SMD command (req %d, rsp %d) completed in %dms\n",
448 		    req_type, hdr->msg_type,
449 		    jiffies_to_msecs(jiffies - start));
450 out:
451 	return ret;
452 }
453 
454 #define __INIT_HAL_MSG(msg_body, type, version) \
455 	do {								\
456 		memset(&(msg_body), 0, sizeof(msg_body));		\
457 		(msg_body).header.msg_type = type;			\
458 		(msg_body).header.msg_version = version;		\
459 		(msg_body).header.len = sizeof(msg_body);		\
460 	} while (0)							\
461 
462 #define INIT_HAL_MSG(msg_body, type)	\
463 	__INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION0)
464 
465 #define INIT_HAL_MSG_V1(msg_body, type) \
466 	__INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION1)
467 
468 #define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \
469 	do { \
470 		memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \
471 		p_msg_body->header.msg_type = WCN36XX_HAL_PROCESS_PTT_REQ; \
472 		p_msg_body->header.msg_version = WCN36XX_HAL_MSG_VERSION0; \
473 		p_msg_body->header.len = sizeof(*p_msg_body) + ppt_msg_len; \
474 	} while (0)
475 
476 #define PREPARE_HAL_BUF(send_buf, msg_body) \
477 	do {							\
478 		memcpy_and_pad(send_buf, msg_body.header.len,	\
479 			       &msg_body, sizeof(msg_body), 0);	\
480 	} while (0)						\
481 
482 #define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \
483 	do {							\
484 		memcpy(send_buf, p_msg_body, p_msg_body->header.len); \
485 	} while (0)
486 
487 static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
488 {
489 	struct wcn36xx_fw_msg_status_rsp *rsp;
490 
491 	if (len < sizeof(struct wcn36xx_hal_msg_header) +
492 	    sizeof(struct wcn36xx_fw_msg_status_rsp))
493 		return -EIO;
494 
495 	rsp = (struct wcn36xx_fw_msg_status_rsp *)
496 		(buf + sizeof(struct wcn36xx_hal_msg_header));
497 
498 	if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
499 		return rsp->status;
500 
501 	return 0;
502 }
503 
504 int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
505 {
506 	struct nv_data *nv_d;
507 	struct wcn36xx_hal_nv_img_download_req_msg msg_body;
508 	int fw_bytes_left;
509 	int ret;
510 	u16 fm_offset = 0;
511 
512 	if (!wcn->nv) {
513 		ret = request_firmware(&wcn->nv, wcn->nv_file, wcn->dev);
514 		if (ret) {
515 			wcn36xx_err("Failed to load nv file %s: %d\n",
516 				    wcn->nv_file, ret);
517 			goto out;
518 		}
519 	}
520 
521 	nv_d = (struct nv_data *)wcn->nv->data;
522 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ);
523 
524 	msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE;
525 
526 	msg_body.frag_number = 0;
527 	/* hal_buf must be protected with  mutex */
528 	mutex_lock(&wcn->hal_mutex);
529 
530 	do {
531 		fw_bytes_left = wcn->nv->size - fm_offset - 4;
532 		if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) {
533 			msg_body.last_fragment = 0;
534 			msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE;
535 		} else {
536 			msg_body.last_fragment = 1;
537 			msg_body.nv_img_buffer_size = fw_bytes_left;
538 
539 			/* Do not forget update general message len */
540 			msg_body.header.len = sizeof(msg_body) + fw_bytes_left;
541 
542 		}
543 
544 		/* Add load NV request message header */
545 		memcpy(wcn->hal_buf, &msg_body,	sizeof(msg_body));
546 
547 		/* Add NV body itself */
548 		memcpy(wcn->hal_buf + sizeof(msg_body),
549 		       &nv_d->table + fm_offset,
550 		       msg_body.nv_img_buffer_size);
551 
552 		ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
553 		if (ret)
554 			goto out_unlock;
555 		ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf,
556 						   wcn->hal_rsp_len);
557 		if (ret) {
558 			wcn36xx_err("hal_load_nv response failed err=%d\n",
559 				    ret);
560 			goto out_unlock;
561 		}
562 		msg_body.frag_number++;
563 		fm_offset += WCN36XX_NV_FRAGMENT_SIZE;
564 
565 	} while (msg_body.last_fragment != 1);
566 
567 out_unlock:
568 	mutex_unlock(&wcn->hal_mutex);
569 out:	return ret;
570 }
571 
572 static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
573 {
574 	struct wcn36xx_hal_mac_start_rsp_msg *rsp;
575 
576 	if (len < sizeof(*rsp))
577 		return -EIO;
578 
579 	rsp = buf;
580 
581 	if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->start_rsp_params.status)
582 		return -EIO;
583 
584 	memcpy(wcn->crm_version, rsp->start_rsp_params.crm_version,
585 	       WCN36XX_HAL_VERSION_LENGTH);
586 	memcpy(wcn->wlan_version, rsp->start_rsp_params.wlan_version,
587 	       WCN36XX_HAL_VERSION_LENGTH);
588 
589 	/* null terminate the strings, just in case */
590 	wcn->crm_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
591 	wcn->wlan_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
592 
593 	wcn->fw_revision = rsp->start_rsp_params.version.revision;
594 	wcn->fw_version = rsp->start_rsp_params.version.version;
595 	wcn->fw_minor = rsp->start_rsp_params.version.minor;
596 	wcn->fw_major = rsp->start_rsp_params.version.major;
597 
598 	if (wcn->first_boot) {
599 		wcn->first_boot = false;
600 		wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n",
601 			     wcn->wlan_version, wcn->crm_version);
602 
603 		wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n",
604 			     wcn->fw_major, wcn->fw_minor,
605 			     wcn->fw_version, wcn->fw_revision,
606 			     rsp->start_rsp_params.stations,
607 			     rsp->start_rsp_params.bssids);
608 	}
609 	return 0;
610 }
611 
612 int wcn36xx_smd_start(struct wcn36xx *wcn)
613 {
614 	struct wcn36xx_hal_mac_start_req_msg msg_body, *body;
615 	int ret;
616 	int i;
617 	size_t len;
618 	int cfg_elements;
619 	static struct wcn36xx_cfg_val *cfg_vals;
620 
621 	mutex_lock(&wcn->hal_mutex);
622 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ);
623 
624 	msg_body.params.type = DRIVER_TYPE_PRODUCTION;
625 	msg_body.params.len = 0;
626 
627 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
628 
629 	body = (struct wcn36xx_hal_mac_start_req_msg *)wcn->hal_buf;
630 	len = body->header.len;
631 
632 	if (wcn->rf_id == RF_IRIS_WCN3680) {
633 		cfg_vals = wcn3680_cfg_vals;
634 		cfg_elements = ARRAY_SIZE(wcn3680_cfg_vals);
635 	} else {
636 		cfg_vals = wcn36xx_cfg_vals;
637 		cfg_elements = ARRAY_SIZE(wcn36xx_cfg_vals);
638 	}
639 
640 	for (i = 0; i < cfg_elements; i++) {
641 		ret = put_cfg_tlv_u32(wcn, &len, cfg_vals[i].cfg_id,
642 				      cfg_vals[i].value);
643 		if (ret)
644 			goto out;
645 	}
646 	body->header.len = len;
647 	body->params.len = len - sizeof(*body);
648 
649 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n",
650 		    msg_body.params.type);
651 
652 	ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
653 	if (ret) {
654 		wcn36xx_err("Sending hal_start failed\n");
655 		goto out;
656 	}
657 
658 	ret = wcn36xx_smd_start_rsp(wcn, wcn->hal_buf, wcn->hal_rsp_len);
659 	if (ret) {
660 		wcn36xx_err("hal_start response failed err=%d\n", ret);
661 		goto out;
662 	}
663 
664 out:
665 	mutex_unlock(&wcn->hal_mutex);
666 	return ret;
667 }
668 
669 int wcn36xx_smd_stop(struct wcn36xx *wcn)
670 {
671 	struct wcn36xx_hal_mac_stop_req_msg msg_body;
672 	int ret;
673 
674 	mutex_lock(&wcn->hal_mutex);
675 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ);
676 
677 	msg_body.stop_req_params.reason = HAL_STOP_TYPE_RF_KILL;
678 
679 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
680 
681 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
682 	if (ret) {
683 		wcn36xx_err("Sending hal_stop failed\n");
684 		goto out;
685 	}
686 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
687 	if (ret) {
688 		wcn36xx_err("hal_stop response failed err=%d\n", ret);
689 		goto out;
690 	}
691 out:
692 	mutex_unlock(&wcn->hal_mutex);
693 	return ret;
694 }
695 
696 int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode,
697 			  struct ieee80211_vif *vif)
698 {
699 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
700 	struct wcn36xx_hal_init_scan_req_msg msg_body;
701 	int ret;
702 
703 	mutex_lock(&wcn->hal_mutex);
704 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ);
705 
706 	msg_body.mode = mode;
707 	if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX) {
708 		/* Notify BSSID with null DATA packet */
709 		msg_body.frame_type = 2;
710 		msg_body.notify = 1;
711 		msg_body.scan_entry.bss_index[0] = vif_priv->bss_index;
712 		msg_body.scan_entry.active_bss_count = 1;
713 	}
714 
715 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
716 
717 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d\n", msg_body.mode);
718 
719 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
720 	if (ret) {
721 		wcn36xx_err("Sending hal_init_scan failed\n");
722 		goto out;
723 	}
724 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
725 	if (ret) {
726 		wcn36xx_err("hal_init_scan response failed err=%d\n", ret);
727 		goto out;
728 	}
729 	wcn->sw_scan_init = true;
730 out:
731 	mutex_unlock(&wcn->hal_mutex);
732 	return ret;
733 }
734 
735 int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel)
736 {
737 	struct wcn36xx_hal_start_scan_req_msg msg_body;
738 	int ret;
739 
740 	mutex_lock(&wcn->hal_mutex);
741 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ);
742 
743 	msg_body.scan_channel = scan_channel;
744 
745 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
746 
747 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start scan channel %d\n",
748 		    msg_body.scan_channel);
749 
750 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
751 	if (ret) {
752 		wcn36xx_err("Sending hal_start_scan failed\n");
753 		goto out;
754 	}
755 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
756 	if (ret) {
757 		wcn36xx_err("hal_start_scan response failed err=%d\n", ret);
758 		goto out;
759 	}
760 	wcn->sw_scan_channel = scan_channel;
761 out:
762 	mutex_unlock(&wcn->hal_mutex);
763 	return ret;
764 }
765 
766 int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel)
767 {
768 	struct wcn36xx_hal_end_scan_req_msg msg_body;
769 	int ret;
770 
771 	mutex_lock(&wcn->hal_mutex);
772 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ);
773 
774 	msg_body.scan_channel = scan_channel;
775 
776 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
777 
778 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d\n",
779 		    msg_body.scan_channel);
780 
781 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
782 	if (ret) {
783 		wcn36xx_err("Sending hal_end_scan failed\n");
784 		goto out;
785 	}
786 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
787 	if (ret) {
788 		wcn36xx_err("hal_end_scan response failed err=%d\n", ret);
789 		goto out;
790 	}
791 	wcn->sw_scan_channel = 0;
792 out:
793 	mutex_unlock(&wcn->hal_mutex);
794 	return ret;
795 }
796 
797 int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
798 			    enum wcn36xx_hal_sys_mode mode,
799 			    struct ieee80211_vif *vif)
800 {
801 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
802 	struct wcn36xx_hal_finish_scan_req_msg msg_body;
803 	int ret;
804 
805 	mutex_lock(&wcn->hal_mutex);
806 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ);
807 
808 	msg_body.mode = mode;
809 	msg_body.oper_channel = WCN36XX_HW_CHANNEL(wcn);
810 	if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX) {
811 		/* Notify BSSID with null data packet */
812 		msg_body.notify = 1;
813 		msg_body.frame_type = 2;
814 		msg_body.scan_entry.bss_index[0] = vif_priv->bss_index;
815 		msg_body.scan_entry.active_bss_count = 1;
816 	}
817 
818 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
819 
820 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal finish scan mode %d\n",
821 		    msg_body.mode);
822 
823 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
824 	if (ret) {
825 		wcn36xx_err("Sending hal_finish_scan failed\n");
826 		goto out;
827 	}
828 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
829 	if (ret) {
830 		wcn36xx_err("hal_finish_scan response failed err=%d\n", ret);
831 		goto out;
832 	}
833 	wcn->sw_scan_init = false;
834 out:
835 	mutex_unlock(&wcn->hal_mutex);
836 	return ret;
837 }
838 
839 int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif,
840 			      struct cfg80211_scan_request *req)
841 {
842 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
843 	struct wcn36xx_hal_start_scan_offload_req_msg *msg_body;
844 	int ret, i;
845 
846 	if (req->ie_len > WCN36XX_MAX_SCAN_IE_LEN)
847 		return -EINVAL;
848 
849 	mutex_lock(&wcn->hal_mutex);
850 	msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
851 	if (!msg_body) {
852 		ret = -ENOMEM;
853 		goto out;
854 	}
855 
856 	INIT_HAL_MSG((*msg_body), WCN36XX_HAL_START_SCAN_OFFLOAD_REQ);
857 
858 	msg_body->scan_type = WCN36XX_HAL_SCAN_TYPE_ACTIVE;
859 	msg_body->min_ch_time = 30;
860 	msg_body->max_ch_time = 100;
861 	msg_body->scan_hidden = 1;
862 	memcpy(msg_body->mac, vif->addr, ETH_ALEN);
863 	msg_body->bss_type = vif_priv->bss_type;
864 	msg_body->p2p_search = vif->p2p;
865 
866 	msg_body->num_ssid = min_t(u8, req->n_ssids, ARRAY_SIZE(msg_body->ssids));
867 	for (i = 0; i < msg_body->num_ssid; i++) {
868 		msg_body->ssids[i].length = min_t(u8, req->ssids[i].ssid_len,
869 						sizeof(msg_body->ssids[i].ssid));
870 		memcpy(msg_body->ssids[i].ssid, req->ssids[i].ssid,
871 		       msg_body->ssids[i].length);
872 	}
873 
874 	msg_body->num_channel = min_t(u8, req->n_channels,
875 				     sizeof(msg_body->channels));
876 	for (i = 0; i < msg_body->num_channel; i++) {
877 		msg_body->channels[i] =
878 			HW_VALUE_CHANNEL(req->channels[i]->hw_value);
879 	}
880 
881 	msg_body->header.len -= WCN36XX_MAX_SCAN_IE_LEN;
882 
883 	if (req->ie_len > 0) {
884 		msg_body->ie_len = req->ie_len;
885 		msg_body->header.len += req->ie_len;
886 		memcpy(msg_body->ie, req->ie, req->ie_len);
887 	}
888 
889 	PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
890 
891 	wcn36xx_dbg(WCN36XX_DBG_HAL,
892 		    "hal start hw-scan (channels: %u; ssids: %u; p2p: %s)\n",
893 		    msg_body->num_channel, msg_body->num_ssid,
894 		    msg_body->p2p_search ? "yes" : "no");
895 
896 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
897 	if (ret) {
898 		wcn36xx_err("Sending hal_start_scan_offload failed\n");
899 		goto out;
900 	}
901 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
902 	if (ret) {
903 		wcn36xx_err("hal_start_scan_offload response failed err=%d\n",
904 			    ret);
905 		goto out;
906 	}
907 out:
908 	kfree(msg_body);
909 	mutex_unlock(&wcn->hal_mutex);
910 	return ret;
911 }
912 
913 int wcn36xx_smd_stop_hw_scan(struct wcn36xx *wcn)
914 {
915 	struct wcn36xx_hal_stop_scan_offload_req_msg msg_body;
916 	int ret;
917 
918 	mutex_lock(&wcn->hal_mutex);
919 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_SCAN_OFFLOAD_REQ);
920 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
921 
922 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal stop hw-scan\n");
923 
924 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
925 	if (ret) {
926 		wcn36xx_err("Sending hal_stop_scan_offload failed\n");
927 		goto out;
928 	}
929 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
930 	if (ret) {
931 		wcn36xx_err("hal_stop_scan_offload response failed err=%d\n",
932 			    ret);
933 		goto out;
934 	}
935 out:
936 	mutex_unlock(&wcn->hal_mutex);
937 	return ret;
938 }
939 
940 int wcn36xx_smd_update_channel_list(struct wcn36xx *wcn, struct cfg80211_scan_request *req)
941 {
942 	struct wcn36xx_hal_update_channel_list_req_msg *msg_body;
943 	int ret, i;
944 
945 	msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
946 	if (!msg_body)
947 		return -ENOMEM;
948 
949 	INIT_HAL_MSG((*msg_body), WCN36XX_HAL_UPDATE_CHANNEL_LIST_REQ);
950 
951 	msg_body->num_channel = min_t(u8, req->n_channels, ARRAY_SIZE(msg_body->channels));
952 	for (i = 0; i < msg_body->num_channel; i++) {
953 		struct wcn36xx_hal_channel_param *param = &msg_body->channels[i];
954 		u32 min_power = WCN36XX_HAL_DEFAULT_MIN_POWER;
955 		u32 ant_gain = WCN36XX_HAL_DEFAULT_ANT_GAIN;
956 
957 		param->mhz = req->channels[i]->center_freq;
958 		param->band_center_freq1 = req->channels[i]->center_freq;
959 		param->band_center_freq2 = 0;
960 
961 		if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR)
962 			param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_PASSIVE;
963 
964 		if (req->channels[i]->flags & IEEE80211_CHAN_RADAR)
965 			param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_DFS;
966 
967 		if (req->channels[i]->band == NL80211_BAND_5GHZ) {
968 			param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_HT;
969 			param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_VHT;
970 			param->channel_info |= WCN36XX_HAL_CHAN_INFO_PHY_11A;
971 		} else {
972 			param->channel_info |= WCN36XX_HAL_CHAN_INFO_PHY_11BG;
973 		}
974 
975 		if (min_power > req->channels[i]->max_power)
976 			min_power = req->channels[i]->max_power;
977 
978 		if (req->channels[i]->max_antenna_gain)
979 			ant_gain = req->channels[i]->max_antenna_gain;
980 
981 		u32p_replace_bits(&param->reg_info_1, min_power,
982 				  WCN36XX_HAL_CHAN_REG1_MIN_PWR_MASK);
983 		u32p_replace_bits(&param->reg_info_1, req->channels[i]->max_power,
984 				  WCN36XX_HAL_CHAN_REG1_MAX_PWR_MASK);
985 		u32p_replace_bits(&param->reg_info_1, req->channels[i]->max_reg_power,
986 				  WCN36XX_HAL_CHAN_REG1_REG_PWR_MASK);
987 		u32p_replace_bits(&param->reg_info_1, 0,
988 				  WCN36XX_HAL_CHAN_REG1_CLASS_ID_MASK);
989 		u32p_replace_bits(&param->reg_info_2, ant_gain,
990 				  WCN36XX_HAL_CHAN_REG2_ANT_GAIN_MASK);
991 
992 		wcn36xx_dbg(WCN36XX_DBG_HAL,
993 			    "%s: freq=%u, channel_info=%08x, reg_info1=%08x, reg_info2=%08x\n",
994 			    __func__, param->mhz, param->channel_info, param->reg_info_1,
995 			    param->reg_info_2);
996 	}
997 
998 	mutex_lock(&wcn->hal_mutex);
999 
1000 	PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
1001 
1002 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
1003 	if (ret) {
1004 		wcn36xx_err("Sending hal_update_channel_list failed\n");
1005 		goto out;
1006 	}
1007 
1008 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1009 	if (ret) {
1010 		wcn36xx_err("hal_update_channel_list response failed err=%d\n", ret);
1011 		goto out;
1012 	}
1013 
1014 out:
1015 	kfree(msg_body);
1016 	mutex_unlock(&wcn->hal_mutex);
1017 	return ret;
1018 }
1019 
1020 static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len)
1021 {
1022 	struct wcn36xx_hal_switch_channel_rsp_msg *rsp;
1023 	int ret;
1024 
1025 	ret = wcn36xx_smd_rsp_status_check(buf, len);
1026 	if (ret)
1027 		return ret;
1028 	rsp = buf;
1029 	wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d\n",
1030 		    rsp->channel_number, rsp->status);
1031 	return ret;
1032 }
1033 
1034 int wcn36xx_smd_switch_channel(struct wcn36xx *wcn,
1035 			       struct ieee80211_vif *vif, int ch)
1036 {
1037 	struct wcn36xx_hal_switch_channel_req_msg msg_body;
1038 	int ret;
1039 
1040 	mutex_lock(&wcn->hal_mutex);
1041 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ);
1042 
1043 	msg_body.channel_number = (u8)ch;
1044 	msg_body.tx_mgmt_power = 0xbf;
1045 	msg_body.max_tx_power = 0xbf;
1046 	memcpy(msg_body.self_sta_mac_addr, vif->addr, ETH_ALEN);
1047 
1048 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1049 
1050 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1051 	if (ret) {
1052 		wcn36xx_err("Sending hal_switch_channel failed\n");
1053 		goto out;
1054 	}
1055 	ret = wcn36xx_smd_switch_channel_rsp(wcn->hal_buf, wcn->hal_rsp_len);
1056 	if (ret) {
1057 		wcn36xx_err("hal_switch_channel response failed err=%d\n", ret);
1058 		goto out;
1059 	}
1060 out:
1061 	mutex_unlock(&wcn->hal_mutex);
1062 	return ret;
1063 }
1064 
1065 static int wcn36xx_smd_process_ptt_msg_rsp(void *buf, size_t len,
1066 					   void **p_ptt_rsp_msg)
1067 {
1068 	struct wcn36xx_hal_process_ptt_msg_rsp_msg *rsp;
1069 	int ret;
1070 
1071 	ret = wcn36xx_smd_rsp_status_check(buf, len);
1072 	if (ret)
1073 		return ret;
1074 
1075 	rsp = buf;
1076 
1077 	wcn36xx_dbg(WCN36XX_DBG_HAL, "process ptt msg responded with length %d\n",
1078 		    rsp->header.len);
1079 	wcn36xx_dbg_dump(WCN36XX_DBG_HAL_DUMP, "HAL_PTT_MSG_RSP:", rsp->ptt_msg,
1080 			 rsp->header.len - sizeof(rsp->ptt_msg_resp_status));
1081 
1082 	if (rsp->header.len > 0) {
1083 		*p_ptt_rsp_msg = kmemdup(rsp->ptt_msg, rsp->header.len,
1084 					 GFP_ATOMIC);
1085 		if (!*p_ptt_rsp_msg)
1086 			return -ENOMEM;
1087 	}
1088 	return ret;
1089 }
1090 
1091 int wcn36xx_smd_process_ptt_msg(struct wcn36xx *wcn,
1092 				struct ieee80211_vif *vif, void *ptt_msg, size_t len,
1093 		void **ptt_rsp_msg)
1094 {
1095 	struct wcn36xx_hal_process_ptt_msg_req_msg *p_msg_body;
1096 	int ret;
1097 
1098 	mutex_lock(&wcn->hal_mutex);
1099 	p_msg_body = kmalloc(
1100 		sizeof(struct wcn36xx_hal_process_ptt_msg_req_msg) + len,
1101 		GFP_ATOMIC);
1102 	if (!p_msg_body) {
1103 		ret = -ENOMEM;
1104 		goto out_nomem;
1105 	}
1106 	INIT_HAL_PTT_MSG(p_msg_body, len);
1107 
1108 	memcpy(&p_msg_body->ptt_msg, ptt_msg, len);
1109 
1110 	PREPARE_HAL_PTT_MSG_BUF(wcn->hal_buf, p_msg_body);
1111 
1112 	ret = wcn36xx_smd_send_and_wait(wcn, p_msg_body->header.len);
1113 	if (ret) {
1114 		wcn36xx_err("Sending hal_process_ptt_msg failed\n");
1115 		goto out;
1116 	}
1117 	ret = wcn36xx_smd_process_ptt_msg_rsp(wcn->hal_buf, wcn->hal_rsp_len,
1118 					      ptt_rsp_msg);
1119 	if (ret) {
1120 		wcn36xx_err("process_ptt_msg response failed err=%d\n", ret);
1121 		goto out;
1122 	}
1123 out:
1124 	kfree(p_msg_body);
1125 out_nomem:
1126 	mutex_unlock(&wcn->hal_mutex);
1127 	return ret;
1128 }
1129 
1130 static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
1131 					struct ieee80211_vif *vif,
1132 					void *buf,
1133 					size_t len)
1134 {
1135 	struct wcn36xx_hal_add_sta_self_rsp_msg *rsp;
1136 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1137 
1138 	if (len < sizeof(*rsp))
1139 		return -EINVAL;
1140 
1141 	rsp = buf;
1142 
1143 	if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1144 		wcn36xx_warn("hal add sta self failure: %d\n",
1145 			     rsp->status);
1146 		return rsp->status;
1147 	}
1148 
1149 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1150 		    "hal add sta self status %d self_sta_index %d dpu_index %d\n",
1151 		    rsp->status, rsp->self_sta_index, rsp->dpu_index);
1152 
1153 	vif_priv->self_sta_index = rsp->self_sta_index;
1154 	vif_priv->self_dpu_desc_index = rsp->dpu_index;
1155 
1156 	return 0;
1157 }
1158 
1159 int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1160 {
1161 	struct wcn36xx_hal_add_sta_self_req msg_body;
1162 	int ret;
1163 
1164 	mutex_lock(&wcn->hal_mutex);
1165 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ);
1166 
1167 	memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN);
1168 
1169 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1170 
1171 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1172 		    "hal add sta self self_addr %pM status %d\n",
1173 		    msg_body.self_addr, msg_body.status);
1174 
1175 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1176 	if (ret) {
1177 		wcn36xx_err("Sending hal_add_sta_self failed\n");
1178 		goto out;
1179 	}
1180 	ret = wcn36xx_smd_add_sta_self_rsp(wcn,
1181 					   vif,
1182 					   wcn->hal_buf,
1183 					   wcn->hal_rsp_len);
1184 	if (ret) {
1185 		wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret);
1186 		goto out;
1187 	}
1188 out:
1189 	mutex_unlock(&wcn->hal_mutex);
1190 	return ret;
1191 }
1192 
1193 int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr)
1194 {
1195 	struct wcn36xx_hal_del_sta_self_req_msg msg_body;
1196 	int ret;
1197 
1198 	mutex_lock(&wcn->hal_mutex);
1199 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ);
1200 
1201 	memcpy(&msg_body.self_addr, addr, ETH_ALEN);
1202 
1203 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1204 
1205 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1206 	if (ret) {
1207 		wcn36xx_err("Sending hal_delete_sta_self failed\n");
1208 		goto out;
1209 	}
1210 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1211 	if (ret) {
1212 		wcn36xx_err("hal_delete_sta_self response failed err=%d\n",
1213 			    ret);
1214 		goto out;
1215 	}
1216 out:
1217 	mutex_unlock(&wcn->hal_mutex);
1218 	return ret;
1219 }
1220 
1221 int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index)
1222 {
1223 	struct wcn36xx_hal_delete_sta_req_msg msg_body;
1224 	int ret;
1225 
1226 	mutex_lock(&wcn->hal_mutex);
1227 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ);
1228 
1229 	msg_body.sta_index = sta_index;
1230 
1231 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1232 
1233 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1234 		    "hal delete sta sta_index %d\n",
1235 		    msg_body.sta_index);
1236 
1237 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1238 	if (ret) {
1239 		wcn36xx_err("Sending hal_delete_sta failed\n");
1240 		goto out;
1241 	}
1242 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1243 	if (ret) {
1244 		wcn36xx_err("hal_delete_sta response failed err=%d\n", ret);
1245 		goto out;
1246 	}
1247 out:
1248 	mutex_unlock(&wcn->hal_mutex);
1249 	return ret;
1250 }
1251 
1252 static int wcn36xx_smd_join_rsp(void *buf, size_t len)
1253 {
1254 	struct wcn36xx_hal_join_rsp_msg *rsp;
1255 
1256 	if (wcn36xx_smd_rsp_status_check(buf, len))
1257 		return -EIO;
1258 
1259 	rsp = buf;
1260 
1261 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1262 		    "hal rsp join status %d tx_mgmt_power %d\n",
1263 		    rsp->status, rsp->tx_mgmt_power);
1264 
1265 	return 0;
1266 }
1267 
1268 int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch)
1269 {
1270 	struct wcn36xx_hal_join_req_msg msg_body;
1271 	int ret;
1272 
1273 	mutex_lock(&wcn->hal_mutex);
1274 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ);
1275 
1276 	memcpy(&msg_body.bssid, bssid, ETH_ALEN);
1277 	memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN);
1278 	msg_body.channel = ch;
1279 
1280 	if (conf_is_ht40_minus(&wcn->hw->conf))
1281 		msg_body.secondary_channel_offset =
1282 			PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
1283 	else if (conf_is_ht40_plus(&wcn->hw->conf))
1284 		msg_body.secondary_channel_offset =
1285 			PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
1286 	else
1287 		msg_body.secondary_channel_offset =
1288 			PHY_SINGLE_CHANNEL_CENTERED;
1289 
1290 	msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE;
1291 
1292 	msg_body.max_tx_power = 0xbf;
1293 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1294 
1295 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1296 		    "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n",
1297 		    msg_body.bssid, msg_body.self_sta_mac_addr,
1298 		    msg_body.channel, msg_body.link_state);
1299 
1300 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1301 	if (ret) {
1302 		wcn36xx_err("Sending hal_join failed\n");
1303 		goto out;
1304 	}
1305 	ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len);
1306 	if (ret) {
1307 		wcn36xx_err("hal_join response failed err=%d\n", ret);
1308 		goto out;
1309 	}
1310 out:
1311 	mutex_unlock(&wcn->hal_mutex);
1312 	return ret;
1313 }
1314 
1315 int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid,
1316 			    const u8 *sta_mac,
1317 			    enum wcn36xx_hal_link_state state)
1318 {
1319 	struct wcn36xx_hal_set_link_state_req_msg msg_body;
1320 	int ret;
1321 
1322 	mutex_lock(&wcn->hal_mutex);
1323 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ);
1324 
1325 	memcpy(&msg_body.bssid, bssid, ETH_ALEN);
1326 	memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN);
1327 	msg_body.state = state;
1328 
1329 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1330 
1331 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1332 		    "hal set link state bssid %pM self_mac_addr %pM state %d\n",
1333 		    msg_body.bssid, msg_body.self_mac_addr, msg_body.state);
1334 
1335 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1336 	if (ret) {
1337 		wcn36xx_err("Sending hal_set_link_st failed\n");
1338 		goto out;
1339 	}
1340 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1341 	if (ret) {
1342 		wcn36xx_err("hal_set_link_st response failed err=%d\n", ret);
1343 		goto out;
1344 	}
1345 out:
1346 	mutex_unlock(&wcn->hal_mutex);
1347 	return ret;
1348 }
1349 
1350 static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn,
1351 			const struct wcn36xx_hal_config_sta_params *orig,
1352 			struct wcn36xx_hal_config_sta_params_v1 *v1)
1353 {
1354 	/* convert orig to v1 format */
1355 	memcpy(&v1->bssid, orig->bssid, ETH_ALEN);
1356 	memcpy(&v1->mac, orig->mac, ETH_ALEN);
1357 	v1->aid = orig->aid;
1358 	v1->type = orig->type;
1359 	v1->short_preamble_supported = orig->short_preamble_supported;
1360 	v1->listen_interval = orig->listen_interval;
1361 	v1->wmm_enabled = orig->wmm_enabled;
1362 	v1->ht_capable = orig->ht_capable;
1363 	v1->tx_channel_width_set = orig->tx_channel_width_set;
1364 	v1->rifs_mode = orig->rifs_mode;
1365 	v1->lsig_txop_protection = orig->lsig_txop_protection;
1366 	v1->max_ampdu_size = orig->max_ampdu_size;
1367 	v1->max_ampdu_density = orig->max_ampdu_density;
1368 	v1->sgi_40mhz = orig->sgi_40mhz;
1369 	v1->sgi_20Mhz = orig->sgi_20Mhz;
1370 	v1->rmf = orig->rmf;
1371 	v1->encrypt_type = orig->encrypt_type;
1372 	v1->action = orig->action;
1373 	v1->uapsd = orig->uapsd;
1374 	v1->max_sp_len = orig->max_sp_len;
1375 	v1->green_field_capable = orig->green_field_capable;
1376 	v1->mimo_ps = orig->mimo_ps;
1377 	v1->delayed_ba_support = orig->delayed_ba_support;
1378 	v1->max_ampdu_duration = orig->max_ampdu_duration;
1379 	v1->dsss_cck_mode_40mhz = orig->dsss_cck_mode_40mhz;
1380 	memcpy(&v1->supported_rates, &orig->supported_rates,
1381 	       sizeof(orig->supported_rates));
1382 	v1->sta_index = orig->sta_index;
1383 	v1->bssid_index = orig->bssid_index;
1384 	v1->p2p = orig->p2p;
1385 }
1386 
1387 static void
1388 wcn36xx_smd_set_sta_params_v1(struct wcn36xx *wcn,
1389 			      struct ieee80211_vif *vif,
1390 			      struct ieee80211_sta *sta,
1391 			      struct wcn36xx_hal_config_sta_params_v1 *sta_par)
1392 {
1393 	struct wcn36xx_sta *sta_priv = NULL;
1394 	struct wcn36xx_hal_config_sta_params sta_par_v0;
1395 
1396 	wcn36xx_smd_set_sta_params(wcn, vif, sta, &sta_par_v0);
1397 	wcn36xx_smd_convert_sta_to_v1(wcn, &sta_par_v0, sta_par);
1398 
1399 	if (sta) {
1400 		sta_priv = wcn36xx_sta_to_priv(sta);
1401 		wcn36xx_smd_set_sta_vht_params(wcn, sta, sta_par);
1402 		wcn36xx_smd_set_sta_ht_ldpc_params(sta, sta_par);
1403 		memcpy(&sta_par->supported_rates, &sta_priv->supported_rates,
1404 		       sizeof(sta_par->supported_rates));
1405 	} else {
1406 		wcn36xx_set_default_rates_v1(&sta_par->supported_rates);
1407 		wcn36xx_smd_set_sta_default_vht_params(wcn, sta_par);
1408 		wcn36xx_smd_set_sta_default_ht_ldpc_params(wcn, sta_par);
1409 	}
1410 }
1411 
1412 static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
1413 				      struct ieee80211_sta *sta,
1414 				      void *buf,
1415 				      size_t len)
1416 {
1417 	struct wcn36xx_hal_config_sta_rsp_msg *rsp;
1418 	struct config_sta_rsp_params *params;
1419 	struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1420 
1421 	if (len < sizeof(*rsp))
1422 		return -EINVAL;
1423 
1424 	rsp = buf;
1425 	params = &rsp->params;
1426 
1427 	if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1428 		wcn36xx_warn("hal config sta response failure: %d\n",
1429 			     params->status);
1430 		return -EIO;
1431 	}
1432 
1433 	sta_priv->sta_index = params->sta_index;
1434 	sta_priv->dpu_desc_index = params->dpu_index;
1435 	sta_priv->ucast_dpu_sign = params->uc_ucast_sig;
1436 
1437 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1438 		    "hal config sta rsp status %d sta_index %d bssid_index %d uc_ucast_sig %d p2p %d\n",
1439 		    params->status, params->sta_index, params->bssid_index,
1440 		    params->uc_ucast_sig, params->p2p);
1441 
1442 	return 0;
1443 }
1444 
1445 static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn,
1446 				     struct ieee80211_vif *vif,
1447 				     struct ieee80211_sta *sta)
1448 {
1449 	struct wcn36xx_hal_config_sta_req_msg_v1 msg_body;
1450 	struct wcn36xx_hal_config_sta_params_v1 *sta_params;
1451 
1452 	if (wcn->rf_id == RF_IRIS_WCN3680) {
1453 		INIT_HAL_MSG_V1(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
1454 	} else {
1455 		INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
1456 		msg_body.header.len -= WCN36XX_DIFF_STA_PARAMS_V1_NOVHT;
1457 	}
1458 
1459 	sta_params = &msg_body.sta_params;
1460 
1461 	wcn36xx_smd_set_sta_params_v1(wcn, vif, sta, sta_params);
1462 
1463 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1464 
1465 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1466 		    "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1467 		    sta_params->action, sta_params->sta_index, sta_params->bssid_index,
1468 		    sta_params->bssid, sta_params->type, sta_params->mac, sta_params->aid);
1469 
1470 	return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1471 }
1472 
1473 static int wcn36xx_smd_config_sta_v0(struct wcn36xx *wcn,
1474 				     struct ieee80211_vif *vif,
1475 				     struct ieee80211_sta *sta)
1476 {
1477 	struct wcn36xx_hal_config_sta_req_msg msg;
1478 	struct wcn36xx_hal_config_sta_params *sta_params;
1479 
1480 	INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ);
1481 
1482 	sta_params = &msg.sta_params;
1483 
1484 	wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1485 
1486 	PREPARE_HAL_BUF(wcn->hal_buf, msg);
1487 
1488 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1489 		    "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1490 		    sta_params->action, sta_params->sta_index,
1491 		    sta_params->bssid_index, sta_params->bssid,
1492 		    sta_params->type, sta_params->mac, sta_params->aid);
1493 
1494 	return wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1495 }
1496 
1497 int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1498 			   struct ieee80211_sta *sta)
1499 {
1500 	int ret;
1501 
1502 	mutex_lock(&wcn->hal_mutex);
1503 
1504 	if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24))
1505 		ret = wcn36xx_smd_config_sta_v1(wcn, vif, sta);
1506 	else
1507 		ret = wcn36xx_smd_config_sta_v0(wcn, vif, sta);
1508 
1509 	if (ret) {
1510 		wcn36xx_err("Sending hal_config_sta failed\n");
1511 		goto out;
1512 	}
1513 	ret = wcn36xx_smd_config_sta_rsp(wcn,
1514 					 sta,
1515 					 wcn->hal_buf,
1516 					 wcn->hal_rsp_len);
1517 	if (ret) {
1518 		wcn36xx_err("hal_config_sta response failed err=%d\n", ret);
1519 		goto out;
1520 	}
1521 out:
1522 	mutex_unlock(&wcn->hal_mutex);
1523 	return ret;
1524 }
1525 
1526 static void wcn36xx_smd_set_bss_params(struct wcn36xx *wcn,
1527 				       struct ieee80211_vif *vif,
1528 				       struct ieee80211_sta *sta,
1529 				       const u8 *bssid,
1530 				       bool update,
1531 				       struct wcn36xx_hal_config_bss_params *bss)
1532 {
1533 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1534 
1535 	WARN_ON(is_zero_ether_addr(bssid));
1536 
1537 	memcpy(&bss->bssid, bssid, ETH_ALEN);
1538 
1539 	memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN);
1540 
1541 	if (vif->type == NL80211_IFTYPE_STATION) {
1542 		bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE;
1543 
1544 		/* STA */
1545 		bss->oper_mode = 1;
1546 		bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE;
1547 	} else if (vif->type == NL80211_IFTYPE_AP ||
1548 		   vif->type == NL80211_IFTYPE_MESH_POINT) {
1549 		bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE;
1550 
1551 		/* AP */
1552 		bss->oper_mode = 0;
1553 		bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE;
1554 	} else if (vif->type == NL80211_IFTYPE_ADHOC) {
1555 		bss->bss_type = WCN36XX_HAL_IBSS_MODE;
1556 
1557 		/* STA */
1558 		bss->oper_mode = 1;
1559 	} else {
1560 		wcn36xx_warn("Unknown type for bss config: %d\n", vif->type);
1561 	}
1562 
1563 	if (vif->type == NL80211_IFTYPE_STATION)
1564 		wcn36xx_smd_set_bss_nw_type(wcn, sta, bss);
1565 	else
1566 		bss->nw_type = WCN36XX_HAL_11N_NW_TYPE;
1567 
1568 	bss->short_slot_time_supported = vif->bss_conf.use_short_slot;
1569 	bss->lla_coexist = 0;
1570 	bss->llb_coexist = 0;
1571 	bss->llg_coexist = 0;
1572 	bss->rifs_mode = 0;
1573 	bss->beacon_interval = vif->bss_conf.beacon_int;
1574 	bss->dtim_period = vif_priv->dtim_period;
1575 
1576 	wcn36xx_smd_set_bss_ht_params(vif, sta, bss);
1577 
1578 	bss->oper_channel = WCN36XX_HW_CHANNEL(wcn);
1579 
1580 	if (conf_is_ht40_minus(&wcn->hw->conf))
1581 		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
1582 	else if (conf_is_ht40_plus(&wcn->hw->conf))
1583 		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
1584 	else
1585 		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE;
1586 
1587 	bss->reserved = 0;
1588 
1589 	/* wcn->ssid is only valid in AP and IBSS mode */
1590 	bss->ssid.length = vif_priv->ssid.length;
1591 	memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length);
1592 
1593 	bss->obss_prot_enabled = 0;
1594 	bss->rmf = 0;
1595 	bss->max_probe_resp_retry_limit = 0;
1596 	bss->hidden_ssid = vif->bss_conf.hidden_ssid;
1597 	bss->proxy_probe_resp = 0;
1598 	bss->edca_params_valid = 0;
1599 
1600 	/* FIXME: set acbe, acbk, acvi and acvo */
1601 
1602 	bss->ext_set_sta_key_param_valid = 0;
1603 
1604 	/* FIXME: set ext_set_sta_key_param */
1605 
1606 	bss->spectrum_mgt_enable = 0;
1607 	bss->tx_mgmt_power = 0;
1608 	bss->max_tx_power = WCN36XX_MAX_POWER(wcn);
1609 	bss->action = update;
1610 
1611 	vif_priv->bss_type = bss->bss_type;
1612 }
1613 
1614 static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
1615 				     struct ieee80211_vif *vif,
1616 				     struct ieee80211_sta *sta_80211,
1617 				     const u8 *bssid,
1618 				     bool update)
1619 {
1620 	struct wcn36xx_hal_config_bss_req_msg_v1 *msg_body;
1621 	struct wcn36xx_hal_config_bss_params_v1 *bss;
1622 	struct wcn36xx_hal_config_bss_params bss_v0;
1623 	struct wcn36xx_hal_config_sta_params_v1 *sta;
1624 	struct cfg80211_chan_def *chandef;
1625 	int ret;
1626 
1627 	msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
1628 	if (!msg_body)
1629 		return -ENOMEM;
1630 
1631 	if (wcn->rf_id == RF_IRIS_WCN3680) {
1632 		INIT_HAL_MSG_V1((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ);
1633 	} else {
1634 		INIT_HAL_MSG((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ);
1635 		msg_body->header.len -= WCN36XX_DIFF_BSS_PARAMS_V1_NOVHT;
1636 	}
1637 
1638 	bss = &msg_body->bss_params;
1639 	sta = &bss->sta;
1640 
1641 	memset(&bss_v0, 0x00, sizeof(bss_v0));
1642 	wcn36xx_smd_set_bss_params(wcn, vif, sta_80211, bssid, update, &bss_v0);
1643 	wcn36xx_smd_set_sta_params_v1(wcn, vif, sta_80211, sta);
1644 
1645 	/* convert orig to v1 */
1646 	memcpy(bss->bssid, &bss_v0.bssid, ETH_ALEN);
1647 	memcpy(bss->self_mac_addr, &bss_v0.self_mac_addr, ETH_ALEN);
1648 
1649 	bss->bss_type = bss_v0.bss_type;
1650 	bss->oper_mode = bss_v0.oper_mode;
1651 	bss->nw_type = bss_v0.nw_type;
1652 
1653 	bss->short_slot_time_supported =
1654 		bss_v0.short_slot_time_supported;
1655 	bss->lla_coexist = bss_v0.lla_coexist;
1656 	bss->llb_coexist = bss_v0.llb_coexist;
1657 	bss->llg_coexist = bss_v0.llg_coexist;
1658 	bss->ht20_coexist = bss_v0.ht20_coexist;
1659 	bss->lln_non_gf_coexist = bss_v0.lln_non_gf_coexist;
1660 
1661 	bss->lsig_tx_op_protection_full_support =
1662 		bss_v0.lsig_tx_op_protection_full_support;
1663 	bss->rifs_mode = bss_v0.rifs_mode;
1664 	bss->beacon_interval = bss_v0.beacon_interval;
1665 	bss->dtim_period = bss_v0.dtim_period;
1666 	bss->tx_channel_width_set = bss_v0.tx_channel_width_set;
1667 	bss->oper_channel = bss_v0.oper_channel;
1668 
1669 	if (wcn->hw->conf.chandef.width == NL80211_CHAN_WIDTH_80) {
1670 		chandef = &wcn->hw->conf.chandef;
1671 		bss->ext_channel = HW_VALUE_PHY(chandef->chan->hw_value);
1672 	} else {
1673 		bss->ext_channel = bss_v0.ext_channel;
1674 	}
1675 
1676 	bss->reserved = bss_v0.reserved;
1677 
1678 	memcpy(&bss->ssid, &bss_v0.ssid,
1679 	       sizeof(bss_v0.ssid));
1680 
1681 	bss->action = bss_v0.action;
1682 	bss->rateset = bss_v0.rateset;
1683 	bss->ht = bss_v0.ht;
1684 	bss->obss_prot_enabled = bss_v0.obss_prot_enabled;
1685 	bss->rmf = bss_v0.rmf;
1686 	bss->ht_oper_mode = bss_v0.ht_oper_mode;
1687 	bss->dual_cts_protection = bss_v0.dual_cts_protection;
1688 
1689 	bss->max_probe_resp_retry_limit =
1690 		bss_v0.max_probe_resp_retry_limit;
1691 	bss->hidden_ssid = bss_v0.hidden_ssid;
1692 	bss->proxy_probe_resp =	bss_v0.proxy_probe_resp;
1693 	bss->edca_params_valid = bss_v0.edca_params_valid;
1694 
1695 	memcpy(&bss->acbe, &bss_v0.acbe,
1696 	       sizeof(bss_v0.acbe));
1697 	memcpy(&bss->acbk, &bss_v0.acbk,
1698 	       sizeof(bss_v0.acbk));
1699 	memcpy(&bss->acvi, &bss_v0.acvi,
1700 	       sizeof(bss_v0.acvi));
1701 	memcpy(&bss->acvo, &bss_v0.acvo,
1702 	       sizeof(bss_v0.acvo));
1703 
1704 	bss->ext_set_sta_key_param_valid =
1705 		bss_v0.ext_set_sta_key_param_valid;
1706 
1707 	memcpy(&bss->ext_set_sta_key_param,
1708 	       &bss_v0.ext_set_sta_key_param,
1709 	       sizeof(bss_v0.acvo));
1710 
1711 	bss->wcn36xx_hal_persona = bss_v0.wcn36xx_hal_persona;
1712 	bss->spectrum_mgt_enable = bss_v0.spectrum_mgt_enable;
1713 	bss->tx_mgmt_power = bss_v0.tx_mgmt_power;
1714 	bss->max_tx_power = bss_v0.max_tx_power;
1715 
1716 	wcn36xx_smd_set_bss_vht_params(vif, sta_80211, bss);
1717 
1718 	PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
1719 
1720 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1721 		    "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1722 		    bss->bssid, bss->self_mac_addr, bss->bss_type,
1723 		    bss->oper_mode, bss->nw_type);
1724 
1725 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1726 		    "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1727 		    sta->bssid, sta->action, sta->sta_index,
1728 		    sta->bssid_index, sta->aid, sta->type, sta->mac);
1729 
1730 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
1731 	kfree(msg_body);
1732 
1733 	return ret;
1734 }
1735 
1736 static int wcn36xx_smd_config_bss_v0(struct wcn36xx *wcn,
1737 				     struct ieee80211_vif *vif,
1738 				     struct ieee80211_sta *sta,
1739 				     const u8 *bssid,
1740 				     bool update)
1741 {
1742 	struct wcn36xx_hal_config_bss_req_msg *msg;
1743 	struct wcn36xx_hal_config_bss_params *bss;
1744 	struct wcn36xx_hal_config_sta_params *sta_params;
1745 	int ret;
1746 
1747 	msg = kzalloc(sizeof(*msg), GFP_KERNEL);
1748 	if (!msg)
1749 		return -ENOMEM;
1750 
1751 	INIT_HAL_MSG((*msg), WCN36XX_HAL_CONFIG_BSS_REQ);
1752 
1753 	bss = &msg->bss_params;
1754 	sta_params = &bss->sta;
1755 
1756 	wcn36xx_smd_set_bss_params(wcn, vif, sta, bssid, update, bss);
1757 	wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1758 
1759 	PREPARE_HAL_BUF(wcn->hal_buf, (*msg));
1760 
1761 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1762 		    "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1763 		    bss->bssid, bss->self_mac_addr, bss->bss_type,
1764 		    bss->oper_mode, bss->nw_type);
1765 
1766 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1767 		    "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1768 		    sta_params->bssid, sta_params->action,
1769 		    sta_params->sta_index, sta_params->bssid_index,
1770 		    sta_params->aid, sta_params->type,
1771 		    sta_params->mac);
1772 
1773 	ret = wcn36xx_smd_send_and_wait(wcn, msg->header.len);
1774 	kfree(msg);
1775 
1776 	return ret;
1777 }
1778 
1779 static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
1780 				      struct ieee80211_vif *vif,
1781 				      struct ieee80211_sta *sta,
1782 				      void *buf,
1783 				      size_t len)
1784 {
1785 	struct wcn36xx_hal_config_bss_rsp_msg *rsp;
1786 	struct wcn36xx_hal_config_bss_rsp_params *params;
1787 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1788 
1789 	if (len < sizeof(*rsp))
1790 		return -EINVAL;
1791 
1792 	rsp = buf;
1793 	params = &rsp->bss_rsp_params;
1794 
1795 	if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1796 		wcn36xx_warn("hal config bss response failure: %d\n",
1797 			     params->status);
1798 		return -EIO;
1799 	}
1800 
1801 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1802 		    "hal config bss rsp status %d bss_idx %d dpu_desc_index %d"
1803 		    " sta_idx %d self_idx %d bcast_idx %d mac %pM"
1804 		    " power %d ucast_dpu_signature %d\n",
1805 		    params->status, params->bss_index, params->dpu_desc_index,
1806 		    params->bss_sta_index, params->bss_self_sta_index,
1807 		    params->bss_bcast_sta_idx, params->mac,
1808 		    params->tx_mgmt_power, params->ucast_dpu_signature);
1809 
1810 	vif_priv->bss_index = params->bss_index;
1811 
1812 	if (sta) {
1813 		struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1814 		sta_priv->bss_sta_index = params->bss_sta_index;
1815 		sta_priv->bss_dpu_desc_index = params->dpu_desc_index;
1816 	}
1817 
1818 	vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature;
1819 
1820 	return 0;
1821 }
1822 
1823 int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1824 			   struct ieee80211_sta *sta, const u8 *bssid,
1825 			   bool update)
1826 {
1827 	int ret;
1828 
1829 	mutex_lock(&wcn->hal_mutex);
1830 
1831 	if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24))
1832 		ret = wcn36xx_smd_config_bss_v1(wcn, vif, sta, bssid, update);
1833 	else
1834 		ret = wcn36xx_smd_config_bss_v0(wcn, vif, sta, bssid, update);
1835 
1836 	if (ret) {
1837 		wcn36xx_err("Sending hal_config_bss failed\n");
1838 		goto out;
1839 	}
1840 	ret = wcn36xx_smd_config_bss_rsp(wcn,
1841 					 vif,
1842 					 sta,
1843 					 wcn->hal_buf,
1844 					 wcn->hal_rsp_len);
1845 	if (ret)
1846 		wcn36xx_err("hal_config_bss response failed err=%d\n", ret);
1847 
1848 out:
1849 	mutex_unlock(&wcn->hal_mutex);
1850 	return ret;
1851 }
1852 
1853 int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1854 {
1855 	struct wcn36xx_hal_delete_bss_req_msg msg_body;
1856 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1857 	int ret = 0;
1858 
1859 	mutex_lock(&wcn->hal_mutex);
1860 
1861 	if (vif_priv->bss_index == WCN36XX_HAL_BSS_INVALID_IDX)
1862 		goto out;
1863 
1864 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ);
1865 
1866 	msg_body.bss_index = vif_priv->bss_index;
1867 
1868 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1869 
1870 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index);
1871 
1872 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1873 	if (ret) {
1874 		wcn36xx_err("Sending hal_delete_bss failed\n");
1875 		goto out;
1876 	}
1877 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1878 	if (ret) {
1879 		wcn36xx_err("hal_delete_bss response failed err=%d\n", ret);
1880 		goto out;
1881 	}
1882 
1883 	vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
1884 out:
1885 	mutex_unlock(&wcn->hal_mutex);
1886 	return ret;
1887 }
1888 
1889 int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1890 			    struct sk_buff *skb_beacon, u16 tim_off,
1891 			    u16 p2p_off)
1892 {
1893 	struct wcn36xx_hal_send_beacon_req_msg msg_body;
1894 	int ret, pad, pvm_len;
1895 
1896 	mutex_lock(&wcn->hal_mutex);
1897 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
1898 
1899 	pvm_len = skb_beacon->data[tim_off + 1] - 3;
1900 	pad = TIM_MIN_PVM_SIZE - pvm_len;
1901 
1902 	/* Padding is irrelevant to mesh mode since tim_off is always 0. */
1903 	if (vif->type == NL80211_IFTYPE_MESH_POINT)
1904 		pad = 0;
1905 
1906 	msg_body.beacon_length = skb_beacon->len + pad;
1907 	/* TODO need to find out why + 6 is needed */
1908 	msg_body.beacon_length6 = msg_body.beacon_length + 6;
1909 
1910 	if (msg_body.beacon_length > BEACON_TEMPLATE_SIZE) {
1911 		wcn36xx_err("Beacon is too big: beacon size=%d\n",
1912 			      msg_body.beacon_length);
1913 		ret = -ENOMEM;
1914 		goto out;
1915 	}
1916 	memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len);
1917 	memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
1918 
1919 	if (pad > 0) {
1920 		/*
1921 		 * The wcn36xx FW has a fixed size for the PVM in the TIM. If
1922 		 * given the beacon template from mac80211 with a PVM shorter
1923 		 * than the FW expectes it will overwrite the data after the
1924 		 * TIM.
1925 		 */
1926 		wcn36xx_dbg(WCN36XX_DBG_HAL, "Pad TIM PVM. %d bytes at %d\n",
1927 			    pad, pvm_len);
1928 		memmove(&msg_body.beacon[tim_off + 5 + pvm_len + pad],
1929 			&msg_body.beacon[tim_off + 5 + pvm_len],
1930 			skb_beacon->len - (tim_off + 5 + pvm_len));
1931 		memset(&msg_body.beacon[tim_off + 5 + pvm_len], 0, pad);
1932 		msg_body.beacon[tim_off + 1] += pad;
1933 	}
1934 
1935 	/* TODO need to find out why this is needed? */
1936 	if (vif->type == NL80211_IFTYPE_MESH_POINT)
1937 		/* mesh beacon don't need this, so push further down */
1938 		msg_body.tim_ie_offset = 256;
1939 	else
1940 		msg_body.tim_ie_offset = tim_off+4;
1941 	msg_body.p2p_ie_offset = p2p_off;
1942 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1943 
1944 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1945 		    "hal send beacon beacon_length %d\n",
1946 		    msg_body.beacon_length);
1947 
1948 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1949 	if (ret) {
1950 		wcn36xx_err("Sending hal_send_beacon failed\n");
1951 		goto out;
1952 	}
1953 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1954 	if (ret) {
1955 		wcn36xx_err("hal_send_beacon response failed err=%d\n", ret);
1956 		goto out;
1957 	}
1958 out:
1959 	mutex_unlock(&wcn->hal_mutex);
1960 	return ret;
1961 }
1962 
1963 int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn,
1964 				      struct ieee80211_vif *vif,
1965 				      struct sk_buff *skb)
1966 {
1967 	struct wcn36xx_hal_send_probe_resp_req_msg msg;
1968 	int ret;
1969 
1970 	mutex_lock(&wcn->hal_mutex);
1971 	INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ);
1972 
1973 	if (skb->len > BEACON_TEMPLATE_SIZE) {
1974 		wcn36xx_warn("probe response template is too big: %d\n",
1975 			     skb->len);
1976 		ret = -E2BIG;
1977 		goto out;
1978 	}
1979 
1980 	msg.probe_resp_template_len = skb->len;
1981 	memcpy(&msg.probe_resp_template, skb->data, skb->len);
1982 
1983 	memcpy(msg.bssid, vif->addr, ETH_ALEN);
1984 
1985 	PREPARE_HAL_BUF(wcn->hal_buf, msg);
1986 
1987 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1988 		    "hal update probe rsp len %d bssid %pM\n",
1989 		    msg.probe_resp_template_len, msg.bssid);
1990 
1991 	ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1992 	if (ret) {
1993 		wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n");
1994 		goto out;
1995 	}
1996 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1997 	if (ret) {
1998 		wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n",
1999 			    ret);
2000 		goto out;
2001 	}
2002 out:
2003 	mutex_unlock(&wcn->hal_mutex);
2004 	return ret;
2005 }
2006 
2007 int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
2008 			   enum ani_ed_type enc_type,
2009 			   u8 keyidx,
2010 			   u8 keylen,
2011 			   u8 *key,
2012 			   u8 sta_index)
2013 {
2014 	struct wcn36xx_hal_set_sta_key_req_msg msg_body;
2015 	int ret;
2016 
2017 	mutex_lock(&wcn->hal_mutex);
2018 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ);
2019 
2020 	msg_body.set_sta_key_params.sta_index = sta_index;
2021 	msg_body.set_sta_key_params.enc_type = enc_type;
2022 
2023 	if (enc_type == WCN36XX_HAL_ED_WEP104 ||
2024 	    enc_type == WCN36XX_HAL_ED_WEP40) {
2025 		/* Use bss key for wep (static) */
2026 		msg_body.set_sta_key_params.def_wep_idx = keyidx;
2027 		msg_body.set_sta_key_params.wep_type = 0;
2028 	} else {
2029 		msg_body.set_sta_key_params.key[0].id = keyidx;
2030 		msg_body.set_sta_key_params.key[0].unicast = 1;
2031 		msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
2032 		msg_body.set_sta_key_params.key[0].pae_role = 0;
2033 		msg_body.set_sta_key_params.key[0].length = keylen;
2034 		memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
2035 	}
2036 
2037 	msg_body.set_sta_key_params.single_tid_rc = 1;
2038 
2039 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2040 
2041 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2042 	if (ret) {
2043 		wcn36xx_err("Sending hal_set_stakey failed\n");
2044 		goto out;
2045 	}
2046 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2047 	if (ret) {
2048 		wcn36xx_err("hal_set_stakey response failed err=%d\n", ret);
2049 		goto out;
2050 	}
2051 out:
2052 	mutex_unlock(&wcn->hal_mutex);
2053 	return ret;
2054 }
2055 
2056 int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn,
2057 			   enum ani_ed_type enc_type,
2058 			   u8 bssidx,
2059 			   u8 keyidx,
2060 			   u8 keylen,
2061 			   u8 *key)
2062 {
2063 	struct wcn36xx_hal_set_bss_key_req_msg msg_body;
2064 	int ret;
2065 
2066 	mutex_lock(&wcn->hal_mutex);
2067 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ);
2068 	msg_body.bss_idx = bssidx;
2069 	msg_body.enc_type = enc_type;
2070 	msg_body.num_keys = 1;
2071 	msg_body.keys[0].id = keyidx;
2072 	msg_body.keys[0].unicast = 0;
2073 	msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY;
2074 	msg_body.keys[0].pae_role = 0;
2075 	msg_body.keys[0].length = keylen;
2076 	memcpy(msg_body.keys[0].key, key, keylen);
2077 
2078 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2079 
2080 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2081 	if (ret) {
2082 		wcn36xx_err("Sending hal_set_bsskey failed\n");
2083 		goto out;
2084 	}
2085 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2086 	if (ret) {
2087 		wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret);
2088 		goto out;
2089 	}
2090 out:
2091 	mutex_unlock(&wcn->hal_mutex);
2092 	return ret;
2093 }
2094 
2095 int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn,
2096 			      enum ani_ed_type enc_type,
2097 			      u8 keyidx,
2098 			      u8 sta_index)
2099 {
2100 	struct wcn36xx_hal_remove_sta_key_req_msg msg_body;
2101 	int ret;
2102 
2103 	mutex_lock(&wcn->hal_mutex);
2104 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ);
2105 
2106 	msg_body.sta_idx = sta_index;
2107 	msg_body.enc_type = enc_type;
2108 	msg_body.key_id = keyidx;
2109 
2110 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2111 
2112 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2113 	if (ret) {
2114 		wcn36xx_err("Sending hal_remove_stakey failed\n");
2115 		goto out;
2116 	}
2117 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2118 	if (ret) {
2119 		wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret);
2120 		goto out;
2121 	}
2122 out:
2123 	mutex_unlock(&wcn->hal_mutex);
2124 	return ret;
2125 }
2126 
2127 int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
2128 			      enum ani_ed_type enc_type,
2129 			      u8 bssidx,
2130 			      u8 keyidx)
2131 {
2132 	struct wcn36xx_hal_remove_bss_key_req_msg msg_body;
2133 	int ret;
2134 
2135 	mutex_lock(&wcn->hal_mutex);
2136 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ);
2137 	msg_body.bss_idx = bssidx;
2138 	msg_body.enc_type = enc_type;
2139 	msg_body.key_id = keyidx;
2140 
2141 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2142 
2143 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2144 	if (ret) {
2145 		wcn36xx_err("Sending hal_remove_bsskey failed\n");
2146 		goto out;
2147 	}
2148 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2149 	if (ret) {
2150 		wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
2151 		goto out;
2152 	}
2153 out:
2154 	mutex_unlock(&wcn->hal_mutex);
2155 	return ret;
2156 }
2157 
2158 int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
2159 {
2160 	struct wcn36xx_hal_enter_bmps_req_msg msg_body;
2161 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2162 	int ret;
2163 
2164 	mutex_lock(&wcn->hal_mutex);
2165 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ);
2166 
2167 	msg_body.bss_index = vif_priv->bss_index;
2168 	msg_body.tbtt = vif->bss_conf.sync_tsf;
2169 	msg_body.dtim_period = vif_priv->dtim_period;
2170 
2171 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2172 
2173 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2174 	if (ret) {
2175 		wcn36xx_err("Sending hal_enter_bmps failed\n");
2176 		goto out;
2177 	}
2178 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2179 	if (ret) {
2180 		wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret);
2181 		goto out;
2182 	}
2183 out:
2184 	mutex_unlock(&wcn->hal_mutex);
2185 	return ret;
2186 }
2187 
2188 int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
2189 {
2190 	struct wcn36xx_hal_exit_bmps_req_msg msg_body;
2191 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2192 	int ret;
2193 
2194 	mutex_lock(&wcn->hal_mutex);
2195 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ);
2196 
2197 	msg_body.bss_index = vif_priv->bss_index;
2198 	msg_body.send_data_null = 1;
2199 
2200 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2201 
2202 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2203 	if (ret) {
2204 		wcn36xx_err("Sending hal_exit_bmps failed\n");
2205 		goto out;
2206 	}
2207 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2208 	if (ret) {
2209 		wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
2210 		goto out;
2211 	}
2212 out:
2213 	mutex_unlock(&wcn->hal_mutex);
2214 	return ret;
2215 }
2216 
2217 int wcn36xx_smd_enter_imps(struct wcn36xx *wcn)
2218 {
2219 	struct wcn36xx_hal_enter_imps_req_msg msg_body;
2220 	int ret;
2221 
2222 	mutex_lock(&wcn->hal_mutex);
2223 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_IMPS_REQ);
2224 
2225 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2226 
2227 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2228 	if (ret) {
2229 		wcn36xx_err("Sending hal_enter_imps failed\n");
2230 		goto out;
2231 	}
2232 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2233 	if (ret) {
2234 		wcn36xx_err("hal_enter_imps response failed err=%d\n", ret);
2235 		goto out;
2236 	}
2237 
2238 	wcn36xx_dbg(WCN36XX_DBG_HAL, "Entered idle mode\n");
2239 out:
2240 	mutex_unlock(&wcn->hal_mutex);
2241 	return ret;
2242 }
2243 
2244 int wcn36xx_smd_exit_imps(struct wcn36xx *wcn)
2245 {
2246 	struct wcn36xx_hal_exit_imps_req_msg msg_body;
2247 	int ret;
2248 
2249 	mutex_lock(&wcn->hal_mutex);
2250 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_IMPS_REQ);
2251 
2252 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2253 
2254 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2255 	if (ret) {
2256 		wcn36xx_err("Sending hal_exit_imps failed\n");
2257 		goto out;
2258 	}
2259 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2260 	if (ret) {
2261 		wcn36xx_err("hal_exit_imps response failed err=%d\n", ret);
2262 		goto out;
2263 	}
2264 	wcn36xx_dbg(WCN36XX_DBG_HAL, "Exited idle mode\n");
2265 out:
2266 	mutex_unlock(&wcn->hal_mutex);
2267 	return ret;
2268 }
2269 
2270 int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim)
2271 {
2272 	struct wcn36xx_hal_set_power_params_req_msg msg_body;
2273 	int ret;
2274 
2275 	mutex_lock(&wcn->hal_mutex);
2276 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ);
2277 
2278 	/*
2279 	 * When host is down ignore every second dtim
2280 	 */
2281 	if (ignore_dtim) {
2282 		msg_body.ignore_dtim = 1;
2283 		msg_body.dtim_period = 2;
2284 	}
2285 	msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
2286 
2287 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2288 
2289 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2290 	if (ret) {
2291 		wcn36xx_err("Sending hal_set_power_params failed\n");
2292 		goto out;
2293 	}
2294 
2295 out:
2296 	mutex_unlock(&wcn->hal_mutex);
2297 	return ret;
2298 }
2299 
2300 /* Notice: This function should be called after associated, or else it
2301  * will be invalid
2302  */
2303 int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
2304 			       struct ieee80211_vif *vif,
2305 			       int packet_type)
2306 {
2307 	struct wcn36xx_hal_keep_alive_req_msg msg_body;
2308 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2309 	int ret;
2310 
2311 	mutex_lock(&wcn->hal_mutex);
2312 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ);
2313 
2314 	if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) {
2315 		msg_body.bss_index = vif_priv->bss_index;
2316 		msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT;
2317 		msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD;
2318 	} else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) {
2319 		/* TODO: it also support ARP response type */
2320 	} else {
2321 		wcn36xx_warn("unknown keep alive packet type %d\n", packet_type);
2322 		ret = -EINVAL;
2323 		goto out;
2324 	}
2325 
2326 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2327 
2328 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2329 	if (ret) {
2330 		wcn36xx_err("Sending hal_keep_alive failed\n");
2331 		goto out;
2332 	}
2333 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2334 	if (ret) {
2335 		wcn36xx_err("hal_keep_alive response failed err=%d\n", ret);
2336 		goto out;
2337 	}
2338 out:
2339 	mutex_unlock(&wcn->hal_mutex);
2340 	return ret;
2341 }
2342 
2343 int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
2344 			     u32 arg3, u32 arg4, u32 arg5)
2345 {
2346 	struct wcn36xx_hal_dump_cmd_req_msg msg_body;
2347 	int ret;
2348 
2349 	mutex_lock(&wcn->hal_mutex);
2350 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ);
2351 
2352 	msg_body.arg1 = arg1;
2353 	msg_body.arg2 = arg2;
2354 	msg_body.arg3 = arg3;
2355 	msg_body.arg4 = arg4;
2356 	msg_body.arg5 = arg5;
2357 
2358 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2359 
2360 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2361 	if (ret) {
2362 		wcn36xx_err("Sending hal_dump_cmd failed\n");
2363 		goto out;
2364 	}
2365 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2366 	if (ret) {
2367 		wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret);
2368 		goto out;
2369 	}
2370 out:
2371 	mutex_unlock(&wcn->hal_mutex);
2372 	return ret;
2373 }
2374 
2375 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
2376 {
2377 	struct wcn36xx_hal_feat_caps_msg msg_body, *rsp;
2378 	int ret, i;
2379 
2380 	mutex_lock(&wcn->hal_mutex);
2381 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
2382 
2383 	wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
2384 	if (wcn->rf_id == RF_IRIS_WCN3680) {
2385 		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, DOT11AC);
2386 		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, WLAN_CH144);
2387 		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps,
2388 					       ANTENNA_DIVERSITY_SELECTION);
2389 	}
2390 
2391 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2392 
2393 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2394 	if (ret) {
2395 		wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
2396 		goto out;
2397 	}
2398 	if (wcn->hal_rsp_len != sizeof(*rsp)) {
2399 		wcn36xx_err("Invalid hal_feature_caps_exchange response");
2400 		goto out;
2401 	}
2402 
2403 	rsp = (struct wcn36xx_hal_feat_caps_msg *) wcn->hal_buf;
2404 
2405 	for (i = 0; i < WCN36XX_HAL_CAPS_SIZE; i++)
2406 		wcn->fw_feat_caps[i] = rsp->feat_caps[i];
2407 out:
2408 	mutex_unlock(&wcn->hal_mutex);
2409 	return ret;
2410 }
2411 
2412 static int wcn36xx_smd_add_ba_session_rsp(void *buf, int len, u8 *session)
2413 {
2414 	struct wcn36xx_hal_add_ba_session_rsp_msg *rsp;
2415 
2416 	if (len < sizeof(*rsp))
2417 		return -EINVAL;
2418 
2419 	rsp = buf;
2420 	if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS)
2421 		return rsp->status;
2422 
2423 	*session = rsp->ba_session_id;
2424 
2425 	return 0;
2426 }
2427 
2428 int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
2429 		struct ieee80211_sta *sta,
2430 		u16 tid,
2431 		u16 *ssn,
2432 		u8 direction,
2433 		u8 sta_index)
2434 {
2435 	struct wcn36xx_hal_add_ba_session_req_msg msg_body;
2436 	u8 session_id;
2437 	int ret;
2438 
2439 	mutex_lock(&wcn->hal_mutex);
2440 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ);
2441 
2442 	msg_body.sta_index = sta_index;
2443 	memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN);
2444 	msg_body.dialog_token = 0x10;
2445 	msg_body.tid = tid;
2446 
2447 	/* Immediate BA because Delayed BA is not supported */
2448 	msg_body.policy = 1;
2449 	msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE;
2450 	msg_body.timeout = 0;
2451 	if (ssn)
2452 		msg_body.ssn = *ssn;
2453 	msg_body.direction = direction;
2454 
2455 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2456 
2457 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2458 	if (ret) {
2459 		wcn36xx_err("Sending hal_add_ba_session failed\n");
2460 		goto out;
2461 	}
2462 	ret = wcn36xx_smd_add_ba_session_rsp(wcn->hal_buf, wcn->hal_rsp_len,
2463 					     &session_id);
2464 	if (ret) {
2465 		wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret);
2466 		ret = -EINVAL;
2467 		goto out;
2468 	}
2469 
2470 	ret = session_id;
2471 out:
2472 	mutex_unlock(&wcn->hal_mutex);
2473 	return ret;
2474 }
2475 
2476 int wcn36xx_smd_add_ba(struct wcn36xx *wcn, u8 session_id)
2477 {
2478 	struct wcn36xx_hal_add_ba_req_msg msg_body;
2479 	int ret;
2480 
2481 	mutex_lock(&wcn->hal_mutex);
2482 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ);
2483 
2484 	msg_body.session_id = session_id;
2485 	msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE;
2486 
2487 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2488 
2489 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2490 	if (ret) {
2491 		wcn36xx_err("Sending hal_add_ba failed\n");
2492 		goto out;
2493 	}
2494 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2495 	if (ret) {
2496 		wcn36xx_err("hal_add_ba response failed err=%d\n", ret);
2497 		goto out;
2498 	}
2499 out:
2500 	mutex_unlock(&wcn->hal_mutex);
2501 	return ret;
2502 }
2503 
2504 int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 direction, u8 sta_index)
2505 {
2506 	struct wcn36xx_hal_del_ba_req_msg msg_body;
2507 	int ret;
2508 
2509 	mutex_lock(&wcn->hal_mutex);
2510 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ);
2511 
2512 	msg_body.sta_index = sta_index;
2513 	msg_body.tid = tid;
2514 	msg_body.direction = direction;
2515 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2516 
2517 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2518 	if (ret) {
2519 		wcn36xx_err("Sending hal_del_ba failed\n");
2520 		goto out;
2521 	}
2522 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2523 	if (ret) {
2524 		wcn36xx_err("hal_del_ba response failed err=%d\n", ret);
2525 		goto out;
2526 	}
2527 out:
2528 	mutex_unlock(&wcn->hal_mutex);
2529 	return ret;
2530 }
2531 
2532 int wcn36xx_smd_get_stats(struct wcn36xx *wcn, u8 sta_index, u32 stats_mask,
2533 			  struct station_info *sinfo)
2534 {
2535 	struct wcn36xx_hal_stats_req_msg msg_body;
2536 	struct wcn36xx_hal_stats_rsp_msg *rsp;
2537 	void *rsp_body;
2538 	int ret;
2539 
2540 	if (stats_mask & ~HAL_GLOBAL_CLASS_A_STATS_INFO) {
2541 		wcn36xx_err("stats_mask 0x%x contains unimplemented types\n",
2542 			    stats_mask);
2543 		return -EINVAL;
2544 	}
2545 
2546 	mutex_lock(&wcn->hal_mutex);
2547 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_GET_STATS_REQ);
2548 
2549 	msg_body.sta_id = sta_index;
2550 	msg_body.stats_mask = stats_mask;
2551 
2552 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2553 
2554 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2555 	if (ret) {
2556 		wcn36xx_err("sending hal_get_stats failed\n");
2557 		goto out;
2558 	}
2559 
2560 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2561 	if (ret) {
2562 		wcn36xx_err("hal_get_stats response failed err=%d\n", ret);
2563 		goto out;
2564 	}
2565 
2566 	rsp = (struct wcn36xx_hal_stats_rsp_msg *)wcn->hal_buf;
2567 	rsp_body = (wcn->hal_buf + sizeof(struct wcn36xx_hal_stats_rsp_msg));
2568 
2569 	if (rsp->stats_mask != stats_mask) {
2570 		wcn36xx_err("stats_mask 0x%x differs from requested 0x%x\n",
2571 			    rsp->stats_mask, stats_mask);
2572 		goto out;
2573 	}
2574 
2575 	if (rsp->stats_mask & HAL_GLOBAL_CLASS_A_STATS_INFO) {
2576 		struct ani_global_class_a_stats_info *stats_info = rsp_body;
2577 
2578 		wcn36xx_process_tx_rate(stats_info, &sinfo->txrate);
2579 		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
2580 		rsp_body += sizeof(struct ani_global_class_a_stats_info);
2581 	}
2582 out:
2583 	mutex_unlock(&wcn->hal_mutex);
2584 
2585 	return ret;
2586 }
2587 
2588 static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len, struct add_ba_info *ba_info)
2589 {
2590 	struct wcn36xx_hal_trigger_ba_rsp_candidate *candidate;
2591 	struct wcn36xx_hal_trigger_ba_rsp_msg *rsp;
2592 	int i;
2593 
2594 	if (len < sizeof(*rsp))
2595 		return -EINVAL;
2596 
2597 	rsp = buf;
2598 
2599 	if (rsp->candidate_cnt < 1)
2600 		return rsp->status ? rsp->status : -EINVAL;
2601 
2602 	candidate = (struct wcn36xx_hal_trigger_ba_rsp_candidate *)(buf + sizeof(*rsp));
2603 
2604 	for (i = 0; i < STACFG_MAX_TC; i++) {
2605 		ba_info[i] = candidate->ba_info[i];
2606 	}
2607 
2608 	return rsp->status;
2609 }
2610 
2611 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u16 *ssn)
2612 {
2613 	struct wcn36xx_hal_trigger_ba_req_msg msg_body;
2614 	struct wcn36xx_hal_trigger_ba_req_candidate *candidate;
2615 	struct add_ba_info ba_info[STACFG_MAX_TC];
2616 	int ret;
2617 
2618 	if (tid >= STACFG_MAX_TC)
2619 		return -EINVAL;
2620 
2621 	mutex_lock(&wcn->hal_mutex);
2622 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
2623 
2624 	msg_body.session_id = 0; /* not really used */
2625 	msg_body.candidate_cnt = 1;
2626 	msg_body.header.len += sizeof(*candidate);
2627 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2628 
2629 	candidate = (struct wcn36xx_hal_trigger_ba_req_candidate *)
2630 		(wcn->hal_buf + sizeof(msg_body));
2631 	candidate->sta_index = sta_index;
2632 	candidate->tid_bitmap = 1 << tid;
2633 
2634 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2635 	if (ret) {
2636 		wcn36xx_err("Sending hal_trigger_ba failed\n");
2637 		goto out;
2638 	}
2639 	ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len, ba_info);
2640 	if (ret) {
2641 		wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
2642 		goto out;
2643 	}
2644 out:
2645 	mutex_unlock(&wcn->hal_mutex);
2646 
2647 	if (ssn)
2648 		*ssn = ba_info[tid].starting_seq_num;
2649 
2650 	return ret;
2651 }
2652 
2653 static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len)
2654 {
2655 	struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf;
2656 
2657 	if (len != sizeof(*rsp)) {
2658 		wcn36xx_warn("Bad TX complete indication\n");
2659 		return -EIO;
2660 	}
2661 
2662 	wcn36xx_dxe_tx_ack_ind(wcn, rsp->status);
2663 
2664 	return 0;
2665 }
2666 
2667 static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, void *buf, size_t len)
2668 {
2669 	struct wcn36xx_hal_scan_offload_ind *rsp = buf;
2670 	struct cfg80211_scan_info scan_info = {};
2671 
2672 	if (len != sizeof(*rsp)) {
2673 		wcn36xx_warn("Corrupted delete scan indication\n");
2674 		return -EIO;
2675 	}
2676 
2677 	wcn36xx_dbg(WCN36XX_DBG_HAL, "scan indication (type %x)\n", rsp->type);
2678 
2679 	switch (rsp->type) {
2680 	case WCN36XX_HAL_SCAN_IND_FAILED:
2681 	case WCN36XX_HAL_SCAN_IND_DEQUEUED:
2682 		scan_info.aborted = true;
2683 		fallthrough;
2684 	case WCN36XX_HAL_SCAN_IND_COMPLETED:
2685 		mutex_lock(&wcn->scan_lock);
2686 		wcn->scan_req = NULL;
2687 		if (wcn->scan_aborted)
2688 			scan_info.aborted = true;
2689 		mutex_unlock(&wcn->scan_lock);
2690 		ieee80211_scan_completed(wcn->hw, &scan_info);
2691 		break;
2692 	case WCN36XX_HAL_SCAN_IND_STARTED:
2693 	case WCN36XX_HAL_SCAN_IND_FOREIGN_CHANNEL:
2694 	case WCN36XX_HAL_SCAN_IND_PREEMPTED:
2695 	case WCN36XX_HAL_SCAN_IND_RESTARTED:
2696 		break;
2697 	default:
2698 		wcn36xx_warn("Unknown scan indication type %x\n", rsp->type);
2699 	}
2700 
2701 	return 0;
2702 }
2703 
2704 static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
2705 					 void *buf,
2706 					 size_t len)
2707 {
2708 	struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf;
2709 	struct ieee80211_vif *vif = NULL;
2710 	struct wcn36xx_vif *tmp;
2711 
2712 	/* Old FW does not have bss index */
2713 	if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
2714 		list_for_each_entry(tmp, &wcn->vif_list, list) {
2715 			wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2716 				    tmp->bss_index);
2717 			vif = wcn36xx_priv_to_vif(tmp);
2718 			ieee80211_beacon_loss(vif);
2719 		}
2720 		return 0;
2721 	}
2722 
2723 	if (len != sizeof(*rsp)) {
2724 		wcn36xx_warn("Corrupted missed beacon indication\n");
2725 		return -EIO;
2726 	}
2727 
2728 	list_for_each_entry(tmp, &wcn->vif_list, list) {
2729 		if (tmp->bss_index == rsp->bss_index) {
2730 			wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2731 				    rsp->bss_index);
2732 			vif = wcn36xx_priv_to_vif(tmp);
2733 			ieee80211_beacon_loss(vif);
2734 			return 0;
2735 		}
2736 	}
2737 
2738 	wcn36xx_warn("BSS index %d not found\n", rsp->bss_index);
2739 	return -ENOENT;
2740 }
2741 
2742 static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
2743 					      void *buf,
2744 					      size_t len)
2745 {
2746 	struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
2747 	struct wcn36xx_vif *vif_priv;
2748 	struct ieee80211_vif *vif;
2749 	struct ieee80211_bss_conf *bss_conf;
2750 	struct ieee80211_sta *sta;
2751 	bool found = false;
2752 
2753 	if (len != sizeof(*rsp)) {
2754 		wcn36xx_warn("Corrupted delete sta indication\n");
2755 		return -EIO;
2756 	}
2757 
2758 	wcn36xx_dbg(WCN36XX_DBG_HAL,
2759 		    "delete station indication %pM index %d reason %d\n",
2760 		    rsp->addr2, rsp->sta_id, rsp->reason_code);
2761 
2762 	list_for_each_entry(vif_priv, &wcn->vif_list, list) {
2763 		rcu_read_lock();
2764 		vif = wcn36xx_priv_to_vif(vif_priv);
2765 
2766 		if (vif->type == NL80211_IFTYPE_STATION) {
2767 			/* We could call ieee80211_find_sta too, but checking
2768 			 * bss_conf is clearer.
2769 			 */
2770 			bss_conf = &vif->bss_conf;
2771 			if (vif_priv->sta_assoc &&
2772 			    !memcmp(bss_conf->bssid, rsp->addr2, ETH_ALEN)) {
2773 				found = true;
2774 				wcn36xx_dbg(WCN36XX_DBG_HAL,
2775 					    "connection loss bss_index %d\n",
2776 					    vif_priv->bss_index);
2777 				ieee80211_connection_loss(vif);
2778 			}
2779 		} else {
2780 			sta = ieee80211_find_sta(vif, rsp->addr2);
2781 			if (sta) {
2782 				found = true;
2783 				ieee80211_report_low_ack(sta, 0);
2784 			}
2785 		}
2786 
2787 		rcu_read_unlock();
2788 		if (found)
2789 			return 0;
2790 	}
2791 
2792 	wcn36xx_warn("BSS or STA with addr %pM not found\n", rsp->addr2);
2793 	return -ENOENT;
2794 }
2795 
2796 static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn,
2797 					  void *buf,
2798 					  size_t len)
2799 {
2800 	struct wcn36xx_hal_print_reg_info_ind *rsp = buf;
2801 	int i;
2802 
2803 	if (len < sizeof(*rsp)) {
2804 		wcn36xx_warn("Corrupted print reg info indication\n");
2805 		return -EIO;
2806 	}
2807 
2808 	wcn36xx_dbg(WCN36XX_DBG_HAL,
2809 		    "reginfo indication, scenario: 0x%x reason: 0x%x\n",
2810 		    rsp->scenario, rsp->reason);
2811 
2812 	for (i = 0; i < rsp->count; i++) {
2813 		wcn36xx_dbg(WCN36XX_DBG_HAL, "\t0x%x: 0x%x\n",
2814 			    rsp->regs[i].addr, rsp->regs[i].value);
2815 	}
2816 
2817 	return 0;
2818 }
2819 
2820 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
2821 {
2822 	struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
2823 	size_t len;
2824 	int ret;
2825 
2826 	mutex_lock(&wcn->hal_mutex);
2827 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ);
2828 
2829 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2830 
2831 	body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf;
2832 	len = msg_body.header.len;
2833 
2834 	put_cfg_tlv_u32(wcn, &len, cfg_id, value);
2835 	body->header.len = len;
2836 	body->len = len - sizeof(*body);
2837 
2838 	ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
2839 	if (ret) {
2840 		wcn36xx_err("Sending hal_update_cfg failed\n");
2841 		goto out;
2842 	}
2843 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2844 	if (ret) {
2845 		wcn36xx_err("hal_update_cfg response failed err=%d\n", ret);
2846 		goto out;
2847 	}
2848 out:
2849 	mutex_unlock(&wcn->hal_mutex);
2850 	return ret;
2851 }
2852 
2853 int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
2854 			    struct ieee80211_vif *vif,
2855 			    struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp)
2856 {
2857 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2858 	struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *msg_body = NULL;
2859 	int ret;
2860 
2861 	mutex_lock(&wcn->hal_mutex);
2862 
2863 	msg_body = (struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *)
2864 		   wcn->hal_buf;
2865 	INIT_HAL_MSG(*msg_body, WCN36XX_HAL_8023_MULTICAST_LIST_REQ);
2866 
2867 	/* An empty list means all mc traffic will be received */
2868 	if (fp)
2869 		memcpy(&msg_body->mc_addr_list, fp,
2870 		       sizeof(msg_body->mc_addr_list));
2871 	else
2872 		msg_body->mc_addr_list.mc_addr_count = 0;
2873 
2874 	msg_body->mc_addr_list.bss_index = vif_priv->bss_index;
2875 
2876 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
2877 	if (ret) {
2878 		wcn36xx_err("Sending HAL_8023_MULTICAST_LIST failed\n");
2879 		goto out;
2880 	}
2881 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2882 	if (ret) {
2883 		wcn36xx_err("HAL_8023_MULTICAST_LIST rsp failed err=%d\n", ret);
2884 		goto out;
2885 	}
2886 out:
2887 	mutex_unlock(&wcn->hal_mutex);
2888 	return ret;
2889 }
2890 
2891 int wcn36xx_smd_arp_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
2892 			    bool enable)
2893 {
2894 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2895 	struct wcn36xx_hal_host_offload_req_msg msg_body;
2896 	int ret;
2897 
2898 	mutex_lock(&wcn->hal_mutex);
2899 
2900 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_OFFLOAD_REQ);
2901 	msg_body.host_offload_params.offload_type =
2902 		WCN36XX_HAL_IPV4_ARP_REPLY_OFFLOAD;
2903 	if (enable) {
2904 		msg_body.host_offload_params.enable =
2905 			WCN36XX_HAL_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
2906 		memcpy(&msg_body.host_offload_params.u,
2907 		       &vif->cfg.arp_addr_list[0], sizeof(__be32));
2908 	}
2909 	msg_body.ns_offload_params.bss_index = vif_priv->bss_index;
2910 
2911 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2912 
2913 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2914 	if (ret) {
2915 		wcn36xx_err("Sending host_offload_arp failed\n");
2916 		goto out;
2917 	}
2918 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2919 	if (ret) {
2920 		wcn36xx_err("host_offload_arp failed err=%d\n", ret);
2921 		goto out;
2922 	}
2923 out:
2924 	mutex_unlock(&wcn->hal_mutex);
2925 	return ret;
2926 }
2927 
2928 #if IS_ENABLED(CONFIG_IPV6)
2929 int wcn36xx_smd_ipv6_ns_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
2930 				bool enable)
2931 {
2932 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2933 	struct wcn36xx_hal_host_offload_req_msg msg_body;
2934 	struct wcn36xx_hal_ns_offload_params *ns_params;
2935 	struct wcn36xx_hal_host_offload_req *ho_params;
2936 	int ret;
2937 
2938 	mutex_lock(&wcn->hal_mutex);
2939 
2940 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_OFFLOAD_REQ);
2941 	ho_params = &msg_body.host_offload_params;
2942 	ns_params = &msg_body.ns_offload_params;
2943 
2944 	ho_params->offload_type = WCN36XX_HAL_IPV6_NS_OFFLOAD;
2945 	if (enable) {
2946 		ho_params->enable =
2947 			WCN36XX_HAL_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE;
2948 		if (vif_priv->num_target_ipv6_addrs) {
2949 			memcpy(&ho_params->u,
2950 			       &vif_priv->target_ipv6_addrs[0].in6_u,
2951 			       sizeof(struct in6_addr));
2952 			memcpy(&ns_params->target_ipv6_addr1,
2953 			       &vif_priv->target_ipv6_addrs[0].in6_u,
2954 			       sizeof(struct in6_addr));
2955 			ns_params->target_ipv6_addr1_valid = 1;
2956 		}
2957 		if (vif_priv->num_target_ipv6_addrs > 1) {
2958 			memcpy(&ns_params->target_ipv6_addr2,
2959 			       &vif_priv->target_ipv6_addrs[1].in6_u,
2960 			       sizeof(struct in6_addr));
2961 			ns_params->target_ipv6_addr2_valid = 1;
2962 		}
2963 	}
2964 	memcpy(&ns_params->self_addr, vif->addr, ETH_ALEN);
2965 	ns_params->bss_index = vif_priv->bss_index;
2966 
2967 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2968 
2969 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2970 	if (ret) {
2971 		wcn36xx_err("Sending host_offload_arp failed\n");
2972 		goto out;
2973 	}
2974 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2975 	if (ret) {
2976 		wcn36xx_err("host_offload_arp failed err=%d\n", ret);
2977 		goto out;
2978 	}
2979 out:
2980 	mutex_unlock(&wcn->hal_mutex);
2981 	return ret;
2982 }
2983 #else
2984 int wcn36xx_smd_ipv6_ns_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
2985 				bool enable)
2986 {
2987 	return 0;
2988 }
2989 #endif
2990 
2991 int wcn36xx_smd_gtk_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
2992 			    bool enable)
2993 {
2994 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2995 	struct wcn36xx_hal_gtk_offload_req_msg msg_body;
2996 	int ret;
2997 
2998 	mutex_lock(&wcn->hal_mutex);
2999 
3000 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_GTK_OFFLOAD_REQ);
3001 
3002 	if (enable) {
3003 		memcpy(&msg_body.kek, vif_priv->rekey_data.kek, NL80211_KEK_LEN);
3004 		memcpy(&msg_body.kck, vif_priv->rekey_data.kck, NL80211_KCK_LEN);
3005 		msg_body.key_replay_counter =
3006 			le64_to_cpu(vif_priv->rekey_data.replay_ctr);
3007 		msg_body.bss_index = vif_priv->bss_index;
3008 	} else {
3009 		msg_body.flags = WCN36XX_HAL_GTK_OFFLOAD_FLAGS_DISABLE;
3010 	}
3011 
3012 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3013 
3014 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3015 	if (ret) {
3016 		wcn36xx_err("Sending host_offload_arp failed\n");
3017 		goto out;
3018 	}
3019 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3020 	if (ret) {
3021 		wcn36xx_err("host_offload_arp failed err=%d\n", ret);
3022 		goto out;
3023 	}
3024 out:
3025 	mutex_unlock(&wcn->hal_mutex);
3026 	return ret;
3027 }
3028 
3029 static int wcn36xx_smd_gtk_offload_get_info_rsp(struct wcn36xx *wcn,
3030 						struct ieee80211_vif *vif)
3031 {
3032 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3033 	struct wcn36xx_hal_gtk_offload_get_info_rsp_msg *rsp;
3034 	__be64 replay_ctr;
3035 
3036 	if (wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len))
3037 		return -EIO;
3038 
3039 	rsp = (struct wcn36xx_hal_gtk_offload_get_info_rsp_msg *)wcn->hal_buf;
3040 
3041 	if (rsp->bss_index != vif_priv->bss_index) {
3042 		wcn36xx_err("gtk_offload_info invalid response bss index %d\n",
3043 			    rsp->bss_index);
3044 		return -ENOENT;
3045 	}
3046 
3047 	if (vif_priv->rekey_data.replay_ctr != cpu_to_le64(rsp->key_replay_counter)) {
3048 		replay_ctr = cpu_to_be64(rsp->key_replay_counter);
3049 		vif_priv->rekey_data.replay_ctr =
3050 			cpu_to_le64(rsp->key_replay_counter);
3051 		ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
3052 					   (void *)&replay_ctr, GFP_KERNEL);
3053 		wcn36xx_dbg(WCN36XX_DBG_HAL,
3054 			    "GTK replay counter increment %llu\n",
3055 			    rsp->key_replay_counter);
3056 	}
3057 
3058 	wcn36xx_dbg(WCN36XX_DBG_HAL,
3059 		    "gtk offload info status %d last_rekey_status %d "
3060 		    "replay_counter %llu total_rekey_count %d gtk_rekey_count %d "
3061 		    "igtk_rekey_count %d bss_index %d\n",
3062 		    rsp->status, rsp->last_rekey_status,
3063 		    rsp->key_replay_counter, rsp->total_rekey_count,
3064 		    rsp->gtk_rekey_count, rsp->igtk_rekey_count,
3065 		    rsp->bss_index);
3066 
3067 	return 0;
3068 }
3069 
3070 int wcn36xx_smd_gtk_offload_get_info(struct wcn36xx *wcn,
3071 				     struct ieee80211_vif *vif)
3072 {
3073 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3074 	struct wcn36xx_hal_gtk_offload_get_info_req_msg msg_body;
3075 	int ret;
3076 
3077 	mutex_lock(&wcn->hal_mutex);
3078 
3079 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_GTK_OFFLOAD_GETINFO_REQ);
3080 
3081 	msg_body.bss_index = vif_priv->bss_index;
3082 
3083 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3084 
3085 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3086 	if (ret) {
3087 		wcn36xx_err("Sending gtk_offload_get_info failed\n");
3088 		goto out;
3089 	}
3090 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3091 	if (ret) {
3092 		wcn36xx_err("gtk_offload_get_info failed err=%d\n", ret);
3093 		goto out;
3094 	}
3095 	ret = wcn36xx_smd_gtk_offload_get_info_rsp(wcn, vif);
3096 out:
3097 	mutex_unlock(&wcn->hal_mutex);
3098 	return ret;
3099 }
3100 
3101 int wcn36xx_smd_wlan_host_suspend_ind(struct wcn36xx *wcn)
3102 {
3103 	struct wcn36xx_hal_wlan_host_suspend_ind_msg msg_body;
3104 	int ret;
3105 
3106 	mutex_lock(&wcn->hal_mutex);
3107 
3108 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_SUSPEND_IND);
3109 	msg_body.configured_mcst_bcst_filter_setting = 0;
3110 	msg_body.active_session_count = 1;
3111 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3112 
3113 	ret = rpmsg_send(wcn->smd_channel, wcn->hal_buf, msg_body.header.len);
3114 
3115 	mutex_unlock(&wcn->hal_mutex);
3116 
3117 	return ret;
3118 }
3119 
3120 int wcn36xx_smd_host_resume(struct wcn36xx *wcn)
3121 {
3122 	struct wcn36xx_hal_wlan_host_resume_req_msg msg_body;
3123 	struct wcn36xx_hal_host_resume_rsp_msg *rsp;
3124 	int ret;
3125 
3126 	mutex_lock(&wcn->hal_mutex);
3127 
3128 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_RESUME_REQ);
3129 	msg_body.configured_mcst_bcst_filter_setting = 0;
3130 
3131 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3132 
3133 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3134 	if (ret) {
3135 		wcn36xx_err("Sending wlan_host_resume failed\n");
3136 		goto out;
3137 	}
3138 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3139 	if (ret) {
3140 		wcn36xx_err("wlan_host_resume err=%d\n", ret);
3141 		goto out;
3142 	}
3143 
3144 	rsp = (struct wcn36xx_hal_host_resume_rsp_msg *)wcn->hal_buf;
3145 	if (rsp->status)
3146 		wcn36xx_warn("wlan_host_resume status=%d\n", rsp->status);
3147 
3148 out:
3149 	mutex_unlock(&wcn->hal_mutex);
3150 
3151 	return ret;
3152 }
3153 
3154 #define BEACON_FILTER(eid, presence, offs, val, mask, ref_val) \
3155 	{					\
3156 		.element_id = eid,		\
3157 		.check_ie_presence = presence,	\
3158 		.offset = offs,			\
3159 		.value = val,			\
3160 		.bitmask = mask,		\
3161 		.ref = ref_val,			\
3162 	}
3163 
3164 static const struct beacon_filter_ie bcn_filter_ies[] = {
3165 	BEACON_FILTER(WLAN_EID_DS_PARAMS, 0, 0, 0,
3166 		      WCN36XX_FILTER_IE_DS_CHANNEL_MASK, 0),
3167 	BEACON_FILTER(WLAN_EID_ERP_INFO, 0, 0, 0,
3168 		      WCN36XX_FILTER_IE_ERP_FILTER_MASK, 0),
3169 	BEACON_FILTER(WLAN_EID_EDCA_PARAM_SET, 0, 0, 0,
3170 		      WCN36XX_FILTER_IE_EDCA_FILTER_MASK, 0),
3171 	BEACON_FILTER(WLAN_EID_QOS_CAPA, 0, 0, 0,
3172 		      WCN36XX_FILTER_IE_QOS_FILTER_MASK, 0),
3173 	BEACON_FILTER(WLAN_EID_CHANNEL_SWITCH, 1, 0, 0,
3174 		      WCN36XX_FILTER_IE_CHANNEL_SWITCH_MASK, 0),
3175 	BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 0, 0,
3176 		      WCN36XX_FILTER_IE_HT_BYTE0_FILTER_MASK, 0),
3177 	BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 2, 0,
3178 		      WCN36XX_FILTER_IE_HT_BYTE2_FILTER_MASK, 0),
3179 	BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 5, 0,
3180 		      WCN36XX_FILTER_IE_HT_BYTE5_FILTER_MASK, 0),
3181 	BEACON_FILTER(WLAN_EID_PWR_CONSTRAINT, 0, 0, 0,
3182 		      WCN36XX_FILTER_IE_PWR_CONSTRAINT_MASK, 0),
3183 	BEACON_FILTER(WLAN_EID_OPMODE_NOTIF, 0, 0, 0,
3184 		      WCN36XX_FILTER_IE_OPMODE_NOTIF_MASK, 0),
3185 	BEACON_FILTER(WLAN_EID_VHT_OPERATION, 0, 0, 0,
3186 		      WCN36XX_FILTER_IE_VHTOP_CHWIDTH_MASK, 0),
3187 	BEACON_FILTER(WLAN_EID_RSN, 1, 0, 0,
3188 		      WCN36XX_FILTER_IE_RSN_MASK, 0),
3189 	BEACON_FILTER(WLAN_EID_VENDOR_SPECIFIC, 1, 0, 0,
3190 		      WCN36XX_FILTER_IE_VENDOR_MASK, 0),
3191 };
3192 
3193 int wcn36xx_smd_add_beacon_filter(struct wcn36xx *wcn,
3194 				  struct ieee80211_vif *vif)
3195 {
3196 	struct wcn36xx_hal_add_bcn_filter_req_msg msg_body, *body;
3197 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3198 	u8 *payload;
3199 	size_t payload_size;
3200 	int ret;
3201 
3202 	if (!wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, BCN_FILTER))
3203 		return -EOPNOTSUPP;
3204 
3205 	mutex_lock(&wcn->hal_mutex);
3206 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BCN_FILTER_REQ);
3207 
3208 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3209 
3210 	body = (struct wcn36xx_hal_add_bcn_filter_req_msg *)wcn->hal_buf;
3211 	body->capability_info = vif->bss_conf.assoc_capability;
3212 	body->capability_mask = WCN36XX_FILTER_CAPABILITY_MASK;
3213 	body->beacon_interval = vif->bss_conf.beacon_int;
3214 	body->ie_num = ARRAY_SIZE(bcn_filter_ies);
3215 	body->bss_index = vif_priv->bss_index;
3216 
3217 	payload = ((u8 *)body) + body->header.len;
3218 	payload_size = sizeof(bcn_filter_ies);
3219 	memcpy(payload, &bcn_filter_ies, payload_size);
3220 
3221 	body->header.len += payload_size;
3222 
3223 	ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
3224 	if (ret) {
3225 		wcn36xx_err("Sending add bcn_filter failed\n");
3226 		goto out;
3227 	}
3228 
3229 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3230 	if (ret) {
3231 		wcn36xx_err("add bcn filter response failed err=%d\n", ret);
3232 		goto out;
3233 	}
3234 out:
3235 	mutex_unlock(&wcn->hal_mutex);
3236 	return ret;
3237 }
3238 
3239 int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
3240 			    void *buf, int len, void *priv, u32 addr)
3241 {
3242 	const struct wcn36xx_hal_msg_header *msg_header = buf;
3243 	struct ieee80211_hw *hw = priv;
3244 	struct wcn36xx *wcn = hw->priv;
3245 	struct wcn36xx_hal_ind_msg *msg_ind;
3246 	wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
3247 
3248 	switch (msg_header->msg_type) {
3249 	case WCN36XX_HAL_START_RSP:
3250 	case WCN36XX_HAL_CONFIG_STA_RSP:
3251 	case WCN36XX_HAL_CONFIG_BSS_RSP:
3252 	case WCN36XX_HAL_ADD_STA_SELF_RSP:
3253 	case WCN36XX_HAL_STOP_RSP:
3254 	case WCN36XX_HAL_DEL_STA_SELF_RSP:
3255 	case WCN36XX_HAL_DELETE_STA_RSP:
3256 	case WCN36XX_HAL_INIT_SCAN_RSP:
3257 	case WCN36XX_HAL_START_SCAN_RSP:
3258 	case WCN36XX_HAL_END_SCAN_RSP:
3259 	case WCN36XX_HAL_FINISH_SCAN_RSP:
3260 	case WCN36XX_HAL_DOWNLOAD_NV_RSP:
3261 	case WCN36XX_HAL_DELETE_BSS_RSP:
3262 	case WCN36XX_HAL_SEND_BEACON_RSP:
3263 	case WCN36XX_HAL_SET_LINK_ST_RSP:
3264 	case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP:
3265 	case WCN36XX_HAL_SET_BSSKEY_RSP:
3266 	case WCN36XX_HAL_SET_STAKEY_RSP:
3267 	case WCN36XX_HAL_RMV_STAKEY_RSP:
3268 	case WCN36XX_HAL_RMV_BSSKEY_RSP:
3269 	case WCN36XX_HAL_ENTER_BMPS_RSP:
3270 	case WCN36XX_HAL_SET_POWER_PARAMS_RSP:
3271 	case WCN36XX_HAL_EXIT_BMPS_RSP:
3272 	case WCN36XX_HAL_KEEP_ALIVE_RSP:
3273 	case WCN36XX_HAL_DUMP_COMMAND_RSP:
3274 	case WCN36XX_HAL_ADD_BA_SESSION_RSP:
3275 	case WCN36XX_HAL_ADD_BA_RSP:
3276 	case WCN36XX_HAL_DEL_BA_RSP:
3277 	case WCN36XX_HAL_GET_STATS_RSP:
3278 	case WCN36XX_HAL_TRIGGER_BA_RSP:
3279 	case WCN36XX_HAL_UPDATE_CFG_RSP:
3280 	case WCN36XX_HAL_JOIN_RSP:
3281 	case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP:
3282 	case WCN36XX_HAL_CH_SWITCH_RSP:
3283 	case WCN36XX_HAL_PROCESS_PTT_RSP:
3284 	case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
3285 	case WCN36XX_HAL_8023_MULTICAST_LIST_RSP:
3286 	case WCN36XX_HAL_START_SCAN_OFFLOAD_RSP:
3287 	case WCN36XX_HAL_STOP_SCAN_OFFLOAD_RSP:
3288 	case WCN36XX_HAL_HOST_OFFLOAD_RSP:
3289 	case WCN36XX_HAL_GTK_OFFLOAD_RSP:
3290 	case WCN36XX_HAL_GTK_OFFLOAD_GETINFO_RSP:
3291 	case WCN36XX_HAL_HOST_RESUME_RSP:
3292 	case WCN36XX_HAL_ENTER_IMPS_RSP:
3293 	case WCN36XX_HAL_EXIT_IMPS_RSP:
3294 	case WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP:
3295 	case WCN36XX_HAL_ADD_BCN_FILTER_RSP:
3296 		memcpy(wcn->hal_buf, buf, len);
3297 		wcn->hal_rsp_len = len;
3298 		complete(&wcn->hal_rsp_compl);
3299 		break;
3300 
3301 	case WCN36XX_HAL_COEX_IND:
3302 	case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
3303 	case WCN36XX_HAL_DEL_BA_IND:
3304 	case WCN36XX_HAL_OTA_TX_COMPL_IND:
3305 	case WCN36XX_HAL_MISSED_BEACON_IND:
3306 	case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
3307 	case WCN36XX_HAL_PRINT_REG_INFO_IND:
3308 	case WCN36XX_HAL_SCAN_OFFLOAD_IND:
3309 		msg_ind = kmalloc(struct_size(msg_ind, msg, len), GFP_ATOMIC);
3310 		if (!msg_ind) {
3311 			wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
3312 				    msg_header->msg_type);
3313 			return -ENOMEM;
3314 		}
3315 
3316 		msg_ind->msg_len = len;
3317 		memcpy(msg_ind->msg, buf, len);
3318 
3319 		spin_lock(&wcn->hal_ind_lock);
3320 		list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
3321 		queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
3322 		spin_unlock(&wcn->hal_ind_lock);
3323 		wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
3324 		break;
3325 	default:
3326 		wcn36xx_err("SMD_EVENT (%d) not supported\n",
3327 			      msg_header->msg_type);
3328 	}
3329 
3330 	return 0;
3331 }
3332 
3333 static void wcn36xx_ind_smd_work(struct work_struct *work)
3334 {
3335 	struct wcn36xx *wcn =
3336 		container_of(work, struct wcn36xx, hal_ind_work);
3337 
3338 	for (;;) {
3339 		struct wcn36xx_hal_msg_header *msg_header;
3340 		struct wcn36xx_hal_ind_msg *hal_ind_msg;
3341 		unsigned long flags;
3342 
3343 		spin_lock_irqsave(&wcn->hal_ind_lock, flags);
3344 
3345 		if (list_empty(&wcn->hal_ind_queue)) {
3346 			spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
3347 			return;
3348 		}
3349 
3350 		hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
3351 					       struct wcn36xx_hal_ind_msg,
3352 					       list);
3353 		list_del(&hal_ind_msg->list);
3354 		spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
3355 
3356 		msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
3357 
3358 		switch (msg_header->msg_type) {
3359 		case WCN36XX_HAL_COEX_IND:
3360 		case WCN36XX_HAL_DEL_BA_IND:
3361 		case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
3362 			break;
3363 		case WCN36XX_HAL_OTA_TX_COMPL_IND:
3364 			wcn36xx_smd_tx_compl_ind(wcn,
3365 						 hal_ind_msg->msg,
3366 						 hal_ind_msg->msg_len);
3367 			break;
3368 		case WCN36XX_HAL_MISSED_BEACON_IND:
3369 			wcn36xx_smd_missed_beacon_ind(wcn,
3370 						      hal_ind_msg->msg,
3371 						      hal_ind_msg->msg_len);
3372 			break;
3373 		case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
3374 			wcn36xx_smd_delete_sta_context_ind(wcn,
3375 							   hal_ind_msg->msg,
3376 							   hal_ind_msg->msg_len);
3377 			break;
3378 		case WCN36XX_HAL_PRINT_REG_INFO_IND:
3379 			wcn36xx_smd_print_reg_info_ind(wcn,
3380 						       hal_ind_msg->msg,
3381 						       hal_ind_msg->msg_len);
3382 			break;
3383 		case WCN36XX_HAL_SCAN_OFFLOAD_IND:
3384 			wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg,
3385 						hal_ind_msg->msg_len);
3386 			break;
3387 		default:
3388 			wcn36xx_err("SMD_EVENT (%d) not supported\n",
3389 				    msg_header->msg_type);
3390 		}
3391 
3392 		kfree(hal_ind_msg);
3393 	}
3394 }
3395 
3396 int wcn36xx_smd_open(struct wcn36xx *wcn)
3397 {
3398 	wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind");
3399 	if (!wcn->hal_ind_wq)
3400 		return -ENOMEM;
3401 
3402 	INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
3403 	INIT_LIST_HEAD(&wcn->hal_ind_queue);
3404 	spin_lock_init(&wcn->hal_ind_lock);
3405 
3406 	return 0;
3407 }
3408 
3409 void wcn36xx_smd_close(struct wcn36xx *wcn)
3410 {
3411 	struct wcn36xx_hal_ind_msg *msg, *tmp;
3412 
3413 	cancel_work_sync(&wcn->hal_ind_work);
3414 	destroy_workqueue(wcn->hal_ind_wq);
3415 
3416 	list_for_each_entry_safe(msg, tmp, &wcn->hal_ind_queue, list)
3417 		kfree(msg);
3418 }
3419