xref: /linux/drivers/net/wireless/ath/wcn36xx/smd.c (revision 0c078e310b6d16b9b9489bbc7bc1476430d19a7c)
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 		memset(send_buf, 0, msg_body.header.len);	\
479 		memcpy(send_buf, &msg_body, sizeof(msg_body));	\
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 = (struct wcn36xx_hal_mac_start_rsp_msg *)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 = (struct wcn36xx_hal_switch_channel_rsp_msg *)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 = (struct wcn36xx_hal_process_ptt_msg_rsp_msg *)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_update_scan_params_rsp(void *buf, size_t len)
1131 {
1132 	struct wcn36xx_hal_update_scan_params_resp *rsp;
1133 
1134 	rsp = (struct wcn36xx_hal_update_scan_params_resp *)buf;
1135 
1136 	/* Remove the PNO version bit */
1137 	rsp->status &= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK));
1138 
1139 	if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) {
1140 		wcn36xx_warn("error response from update scan\n");
1141 		return rsp->status;
1142 	}
1143 
1144 	return 0;
1145 }
1146 
1147 int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn,
1148 				   u8 *channels, size_t channel_count)
1149 {
1150 	struct wcn36xx_hal_update_scan_params_req_ex msg_body;
1151 	int ret;
1152 
1153 	mutex_lock(&wcn->hal_mutex);
1154 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ);
1155 
1156 	msg_body.dot11d_enabled	= false;
1157 	msg_body.dot11d_resolved = true;
1158 
1159 	msg_body.channel_count = channel_count;
1160 	memcpy(msg_body.channels, channels, channel_count);
1161 	msg_body.active_min_ch_time = 60;
1162 	msg_body.active_max_ch_time = 120;
1163 	msg_body.passive_min_ch_time = 60;
1164 	msg_body.passive_max_ch_time = 110;
1165 	msg_body.state = PHY_SINGLE_CHANNEL_CENTERED;
1166 
1167 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1168 
1169 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1170 		    "hal update scan params channel_count %d\n",
1171 		    msg_body.channel_count);
1172 
1173 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1174 	if (ret) {
1175 		wcn36xx_err("Sending hal_update_scan_params failed\n");
1176 		goto out;
1177 	}
1178 	ret = wcn36xx_smd_update_scan_params_rsp(wcn->hal_buf,
1179 						 wcn->hal_rsp_len);
1180 	if (ret) {
1181 		wcn36xx_err("hal_update_scan_params response failed err=%d\n",
1182 			    ret);
1183 		goto out;
1184 	}
1185 out:
1186 	mutex_unlock(&wcn->hal_mutex);
1187 	return ret;
1188 }
1189 
1190 static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
1191 					struct ieee80211_vif *vif,
1192 					void *buf,
1193 					size_t len)
1194 {
1195 	struct wcn36xx_hal_add_sta_self_rsp_msg *rsp;
1196 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1197 
1198 	if (len < sizeof(*rsp))
1199 		return -EINVAL;
1200 
1201 	rsp = (struct wcn36xx_hal_add_sta_self_rsp_msg *)buf;
1202 
1203 	if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1204 		wcn36xx_warn("hal add sta self failure: %d\n",
1205 			     rsp->status);
1206 		return rsp->status;
1207 	}
1208 
1209 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1210 		    "hal add sta self status %d self_sta_index %d dpu_index %d\n",
1211 		    rsp->status, rsp->self_sta_index, rsp->dpu_index);
1212 
1213 	vif_priv->self_sta_index = rsp->self_sta_index;
1214 	vif_priv->self_dpu_desc_index = rsp->dpu_index;
1215 
1216 	return 0;
1217 }
1218 
1219 int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1220 {
1221 	struct wcn36xx_hal_add_sta_self_req msg_body;
1222 	int ret;
1223 
1224 	mutex_lock(&wcn->hal_mutex);
1225 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ);
1226 
1227 	memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN);
1228 
1229 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1230 
1231 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1232 		    "hal add sta self self_addr %pM status %d\n",
1233 		    msg_body.self_addr, msg_body.status);
1234 
1235 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1236 	if (ret) {
1237 		wcn36xx_err("Sending hal_add_sta_self failed\n");
1238 		goto out;
1239 	}
1240 	ret = wcn36xx_smd_add_sta_self_rsp(wcn,
1241 					   vif,
1242 					   wcn->hal_buf,
1243 					   wcn->hal_rsp_len);
1244 	if (ret) {
1245 		wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret);
1246 		goto out;
1247 	}
1248 out:
1249 	mutex_unlock(&wcn->hal_mutex);
1250 	return ret;
1251 }
1252 
1253 int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr)
1254 {
1255 	struct wcn36xx_hal_del_sta_self_req_msg msg_body;
1256 	int ret;
1257 
1258 	mutex_lock(&wcn->hal_mutex);
1259 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ);
1260 
1261 	memcpy(&msg_body.self_addr, addr, ETH_ALEN);
1262 
1263 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1264 
1265 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1266 	if (ret) {
1267 		wcn36xx_err("Sending hal_delete_sta_self failed\n");
1268 		goto out;
1269 	}
1270 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1271 	if (ret) {
1272 		wcn36xx_err("hal_delete_sta_self response failed err=%d\n",
1273 			    ret);
1274 		goto out;
1275 	}
1276 out:
1277 	mutex_unlock(&wcn->hal_mutex);
1278 	return ret;
1279 }
1280 
1281 int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index)
1282 {
1283 	struct wcn36xx_hal_delete_sta_req_msg msg_body;
1284 	int ret;
1285 
1286 	mutex_lock(&wcn->hal_mutex);
1287 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ);
1288 
1289 	msg_body.sta_index = sta_index;
1290 
1291 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1292 
1293 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1294 		    "hal delete sta sta_index %d\n",
1295 		    msg_body.sta_index);
1296 
1297 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1298 	if (ret) {
1299 		wcn36xx_err("Sending hal_delete_sta failed\n");
1300 		goto out;
1301 	}
1302 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1303 	if (ret) {
1304 		wcn36xx_err("hal_delete_sta response failed err=%d\n", ret);
1305 		goto out;
1306 	}
1307 out:
1308 	mutex_unlock(&wcn->hal_mutex);
1309 	return ret;
1310 }
1311 
1312 static int wcn36xx_smd_join_rsp(void *buf, size_t len)
1313 {
1314 	struct wcn36xx_hal_join_rsp_msg *rsp;
1315 
1316 	if (wcn36xx_smd_rsp_status_check(buf, len))
1317 		return -EIO;
1318 
1319 	rsp = (struct wcn36xx_hal_join_rsp_msg *)buf;
1320 
1321 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1322 		    "hal rsp join status %d tx_mgmt_power %d\n",
1323 		    rsp->status, rsp->tx_mgmt_power);
1324 
1325 	return 0;
1326 }
1327 
1328 int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch)
1329 {
1330 	struct wcn36xx_hal_join_req_msg msg_body;
1331 	int ret;
1332 
1333 	mutex_lock(&wcn->hal_mutex);
1334 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ);
1335 
1336 	memcpy(&msg_body.bssid, bssid, ETH_ALEN);
1337 	memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN);
1338 	msg_body.channel = ch;
1339 
1340 	if (conf_is_ht40_minus(&wcn->hw->conf))
1341 		msg_body.secondary_channel_offset =
1342 			PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
1343 	else if (conf_is_ht40_plus(&wcn->hw->conf))
1344 		msg_body.secondary_channel_offset =
1345 			PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
1346 	else
1347 		msg_body.secondary_channel_offset =
1348 			PHY_SINGLE_CHANNEL_CENTERED;
1349 
1350 	msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE;
1351 
1352 	msg_body.max_tx_power = 0xbf;
1353 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1354 
1355 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1356 		    "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n",
1357 		    msg_body.bssid, msg_body.self_sta_mac_addr,
1358 		    msg_body.channel, msg_body.link_state);
1359 
1360 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1361 	if (ret) {
1362 		wcn36xx_err("Sending hal_join failed\n");
1363 		goto out;
1364 	}
1365 	ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len);
1366 	if (ret) {
1367 		wcn36xx_err("hal_join response failed err=%d\n", ret);
1368 		goto out;
1369 	}
1370 out:
1371 	mutex_unlock(&wcn->hal_mutex);
1372 	return ret;
1373 }
1374 
1375 int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid,
1376 			    const u8 *sta_mac,
1377 			    enum wcn36xx_hal_link_state state)
1378 {
1379 	struct wcn36xx_hal_set_link_state_req_msg msg_body;
1380 	int ret;
1381 
1382 	mutex_lock(&wcn->hal_mutex);
1383 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ);
1384 
1385 	memcpy(&msg_body.bssid, bssid, ETH_ALEN);
1386 	memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN);
1387 	msg_body.state = state;
1388 
1389 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1390 
1391 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1392 		    "hal set link state bssid %pM self_mac_addr %pM state %d\n",
1393 		    msg_body.bssid, msg_body.self_mac_addr, msg_body.state);
1394 
1395 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1396 	if (ret) {
1397 		wcn36xx_err("Sending hal_set_link_st failed\n");
1398 		goto out;
1399 	}
1400 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1401 	if (ret) {
1402 		wcn36xx_err("hal_set_link_st response failed err=%d\n", ret);
1403 		goto out;
1404 	}
1405 out:
1406 	mutex_unlock(&wcn->hal_mutex);
1407 	return ret;
1408 }
1409 
1410 static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn,
1411 			const struct wcn36xx_hal_config_sta_params *orig,
1412 			struct wcn36xx_hal_config_sta_params_v1 *v1)
1413 {
1414 	/* convert orig to v1 format */
1415 	memcpy(&v1->bssid, orig->bssid, ETH_ALEN);
1416 	memcpy(&v1->mac, orig->mac, ETH_ALEN);
1417 	v1->aid = orig->aid;
1418 	v1->type = orig->type;
1419 	v1->short_preamble_supported = orig->short_preamble_supported;
1420 	v1->listen_interval = orig->listen_interval;
1421 	v1->wmm_enabled = orig->wmm_enabled;
1422 	v1->ht_capable = orig->ht_capable;
1423 	v1->tx_channel_width_set = orig->tx_channel_width_set;
1424 	v1->rifs_mode = orig->rifs_mode;
1425 	v1->lsig_txop_protection = orig->lsig_txop_protection;
1426 	v1->max_ampdu_size = orig->max_ampdu_size;
1427 	v1->max_ampdu_density = orig->max_ampdu_density;
1428 	v1->sgi_40mhz = orig->sgi_40mhz;
1429 	v1->sgi_20Mhz = orig->sgi_20Mhz;
1430 	v1->rmf = orig->rmf;
1431 	v1->encrypt_type = orig->encrypt_type;
1432 	v1->action = orig->action;
1433 	v1->uapsd = orig->uapsd;
1434 	v1->max_sp_len = orig->max_sp_len;
1435 	v1->green_field_capable = orig->green_field_capable;
1436 	v1->mimo_ps = orig->mimo_ps;
1437 	v1->delayed_ba_support = orig->delayed_ba_support;
1438 	v1->max_ampdu_duration = orig->max_ampdu_duration;
1439 	v1->dsss_cck_mode_40mhz = orig->dsss_cck_mode_40mhz;
1440 	memcpy(&v1->supported_rates, &orig->supported_rates,
1441 	       sizeof(orig->supported_rates));
1442 	v1->sta_index = orig->sta_index;
1443 	v1->bssid_index = orig->bssid_index;
1444 	v1->p2p = orig->p2p;
1445 }
1446 
1447 static void
1448 wcn36xx_smd_set_sta_params_v1(struct wcn36xx *wcn,
1449 			      struct ieee80211_vif *vif,
1450 			      struct ieee80211_sta *sta,
1451 			      struct wcn36xx_hal_config_sta_params_v1 *sta_par)
1452 {
1453 	struct wcn36xx_sta *sta_priv = NULL;
1454 	struct wcn36xx_hal_config_sta_params sta_par_v0;
1455 
1456 	wcn36xx_smd_set_sta_params(wcn, vif, sta, &sta_par_v0);
1457 	wcn36xx_smd_convert_sta_to_v1(wcn, &sta_par_v0, sta_par);
1458 
1459 	if (sta) {
1460 		sta_priv = wcn36xx_sta_to_priv(sta);
1461 		wcn36xx_smd_set_sta_vht_params(wcn, sta, sta_par);
1462 		wcn36xx_smd_set_sta_ht_ldpc_params(sta, sta_par);
1463 		memcpy(&sta_par->supported_rates, &sta_priv->supported_rates,
1464 		       sizeof(sta_par->supported_rates));
1465 	} else {
1466 		wcn36xx_set_default_rates_v1(&sta_par->supported_rates);
1467 		wcn36xx_smd_set_sta_default_vht_params(wcn, sta_par);
1468 		wcn36xx_smd_set_sta_default_ht_ldpc_params(wcn, sta_par);
1469 	}
1470 }
1471 
1472 static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
1473 				      struct ieee80211_sta *sta,
1474 				      void *buf,
1475 				      size_t len)
1476 {
1477 	struct wcn36xx_hal_config_sta_rsp_msg *rsp;
1478 	struct config_sta_rsp_params *params;
1479 	struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1480 
1481 	if (len < sizeof(*rsp))
1482 		return -EINVAL;
1483 
1484 	rsp = (struct wcn36xx_hal_config_sta_rsp_msg *)buf;
1485 	params = &rsp->params;
1486 
1487 	if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1488 		wcn36xx_warn("hal config sta response failure: %d\n",
1489 			     params->status);
1490 		return -EIO;
1491 	}
1492 
1493 	sta_priv->sta_index = params->sta_index;
1494 	sta_priv->dpu_desc_index = params->dpu_index;
1495 	sta_priv->ucast_dpu_sign = params->uc_ucast_sig;
1496 
1497 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1498 		    "hal config sta rsp status %d sta_index %d bssid_index %d uc_ucast_sig %d p2p %d\n",
1499 		    params->status, params->sta_index, params->bssid_index,
1500 		    params->uc_ucast_sig, params->p2p);
1501 
1502 	return 0;
1503 }
1504 
1505 static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn,
1506 				     struct ieee80211_vif *vif,
1507 				     struct ieee80211_sta *sta)
1508 {
1509 	struct wcn36xx_hal_config_sta_req_msg_v1 msg_body;
1510 	struct wcn36xx_hal_config_sta_params_v1 *sta_params;
1511 
1512 	if (wcn->rf_id == RF_IRIS_WCN3680) {
1513 		INIT_HAL_MSG_V1(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
1514 	} else {
1515 		INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
1516 		msg_body.header.len -= WCN36XX_DIFF_STA_PARAMS_V1_NOVHT;
1517 	}
1518 
1519 	sta_params = &msg_body.sta_params;
1520 
1521 	wcn36xx_smd_set_sta_params_v1(wcn, vif, sta, sta_params);
1522 
1523 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1524 
1525 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1526 		    "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1527 		    sta_params->action, sta_params->sta_index, sta_params->bssid_index,
1528 		    sta_params->bssid, sta_params->type, sta_params->mac, sta_params->aid);
1529 
1530 	return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1531 }
1532 
1533 static int wcn36xx_smd_config_sta_v0(struct wcn36xx *wcn,
1534 				     struct ieee80211_vif *vif,
1535 				     struct ieee80211_sta *sta)
1536 {
1537 	struct wcn36xx_hal_config_sta_req_msg msg;
1538 	struct wcn36xx_hal_config_sta_params *sta_params;
1539 
1540 	INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ);
1541 
1542 	sta_params = &msg.sta_params;
1543 
1544 	wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1545 
1546 	PREPARE_HAL_BUF(wcn->hal_buf, msg);
1547 
1548 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1549 		    "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1550 		    sta_params->action, sta_params->sta_index,
1551 		    sta_params->bssid_index, sta_params->bssid,
1552 		    sta_params->type, sta_params->mac, sta_params->aid);
1553 
1554 	return wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1555 }
1556 
1557 int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1558 			   struct ieee80211_sta *sta)
1559 {
1560 	int ret;
1561 
1562 	mutex_lock(&wcn->hal_mutex);
1563 
1564 	if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24))
1565 		ret = wcn36xx_smd_config_sta_v1(wcn, vif, sta);
1566 	else
1567 		ret = wcn36xx_smd_config_sta_v0(wcn, vif, sta);
1568 
1569 	if (ret) {
1570 		wcn36xx_err("Sending hal_config_sta failed\n");
1571 		goto out;
1572 	}
1573 	ret = wcn36xx_smd_config_sta_rsp(wcn,
1574 					 sta,
1575 					 wcn->hal_buf,
1576 					 wcn->hal_rsp_len);
1577 	if (ret) {
1578 		wcn36xx_err("hal_config_sta response failed err=%d\n", ret);
1579 		goto out;
1580 	}
1581 out:
1582 	mutex_unlock(&wcn->hal_mutex);
1583 	return ret;
1584 }
1585 
1586 static void wcn36xx_smd_set_bss_params(struct wcn36xx *wcn,
1587 				       struct ieee80211_vif *vif,
1588 				       struct ieee80211_sta *sta,
1589 				       const u8 *bssid,
1590 				       bool update,
1591 				       struct wcn36xx_hal_config_bss_params *bss)
1592 {
1593 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1594 
1595 	WARN_ON(is_zero_ether_addr(bssid));
1596 
1597 	memcpy(&bss->bssid, bssid, ETH_ALEN);
1598 
1599 	memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN);
1600 
1601 	if (vif->type == NL80211_IFTYPE_STATION) {
1602 		bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE;
1603 
1604 		/* STA */
1605 		bss->oper_mode = 1;
1606 		bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE;
1607 	} else if (vif->type == NL80211_IFTYPE_AP ||
1608 		   vif->type == NL80211_IFTYPE_MESH_POINT) {
1609 		bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE;
1610 
1611 		/* AP */
1612 		bss->oper_mode = 0;
1613 		bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE;
1614 	} else if (vif->type == NL80211_IFTYPE_ADHOC) {
1615 		bss->bss_type = WCN36XX_HAL_IBSS_MODE;
1616 
1617 		/* STA */
1618 		bss->oper_mode = 1;
1619 	} else {
1620 		wcn36xx_warn("Unknown type for bss config: %d\n", vif->type);
1621 	}
1622 
1623 	if (vif->type == NL80211_IFTYPE_STATION)
1624 		wcn36xx_smd_set_bss_nw_type(wcn, sta, bss);
1625 	else
1626 		bss->nw_type = WCN36XX_HAL_11N_NW_TYPE;
1627 
1628 	bss->short_slot_time_supported = vif->bss_conf.use_short_slot;
1629 	bss->lla_coexist = 0;
1630 	bss->llb_coexist = 0;
1631 	bss->llg_coexist = 0;
1632 	bss->rifs_mode = 0;
1633 	bss->beacon_interval = vif->bss_conf.beacon_int;
1634 	bss->dtim_period = vif_priv->dtim_period;
1635 
1636 	wcn36xx_smd_set_bss_ht_params(vif, sta, bss);
1637 
1638 	bss->oper_channel = WCN36XX_HW_CHANNEL(wcn);
1639 
1640 	if (conf_is_ht40_minus(&wcn->hw->conf))
1641 		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
1642 	else if (conf_is_ht40_plus(&wcn->hw->conf))
1643 		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
1644 	else
1645 		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE;
1646 
1647 	bss->reserved = 0;
1648 
1649 	/* wcn->ssid is only valid in AP and IBSS mode */
1650 	bss->ssid.length = vif_priv->ssid.length;
1651 	memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length);
1652 
1653 	bss->obss_prot_enabled = 0;
1654 	bss->rmf = 0;
1655 	bss->max_probe_resp_retry_limit = 0;
1656 	bss->hidden_ssid = vif->bss_conf.hidden_ssid;
1657 	bss->proxy_probe_resp = 0;
1658 	bss->edca_params_valid = 0;
1659 
1660 	/* FIXME: set acbe, acbk, acvi and acvo */
1661 
1662 	bss->ext_set_sta_key_param_valid = 0;
1663 
1664 	/* FIXME: set ext_set_sta_key_param */
1665 
1666 	bss->spectrum_mgt_enable = 0;
1667 	bss->tx_mgmt_power = 0;
1668 	bss->max_tx_power = WCN36XX_MAX_POWER(wcn);
1669 	bss->action = update;
1670 
1671 	vif_priv->bss_type = bss->bss_type;
1672 }
1673 
1674 static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
1675 				     struct ieee80211_vif *vif,
1676 				     struct ieee80211_sta *sta_80211,
1677 				     const u8 *bssid,
1678 				     bool update)
1679 {
1680 	struct wcn36xx_hal_config_bss_req_msg_v1 *msg_body;
1681 	struct wcn36xx_hal_config_bss_params_v1 *bss;
1682 	struct wcn36xx_hal_config_bss_params bss_v0;
1683 	struct wcn36xx_hal_config_sta_params_v1 *sta;
1684 	struct cfg80211_chan_def *chandef;
1685 	int ret;
1686 
1687 	msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
1688 	if (!msg_body)
1689 		return -ENOMEM;
1690 
1691 	if (wcn->rf_id == RF_IRIS_WCN3680) {
1692 		INIT_HAL_MSG_V1((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ);
1693 	} else {
1694 		INIT_HAL_MSG((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ);
1695 		msg_body->header.len -= WCN36XX_DIFF_BSS_PARAMS_V1_NOVHT;
1696 	}
1697 
1698 	bss = &msg_body->bss_params;
1699 	sta = &bss->sta;
1700 
1701 	memset(&bss_v0, 0x00, sizeof(bss_v0));
1702 	wcn36xx_smd_set_bss_params(wcn, vif, sta_80211, bssid, update, &bss_v0);
1703 	wcn36xx_smd_set_sta_params_v1(wcn, vif, sta_80211, sta);
1704 
1705 	/* convert orig to v1 */
1706 	memcpy(bss->bssid, &bss_v0.bssid, ETH_ALEN);
1707 	memcpy(bss->self_mac_addr, &bss_v0.self_mac_addr, ETH_ALEN);
1708 
1709 	bss->bss_type = bss_v0.bss_type;
1710 	bss->oper_mode = bss_v0.oper_mode;
1711 	bss->nw_type = bss_v0.nw_type;
1712 
1713 	bss->short_slot_time_supported =
1714 		bss_v0.short_slot_time_supported;
1715 	bss->lla_coexist = bss_v0.lla_coexist;
1716 	bss->llb_coexist = bss_v0.llb_coexist;
1717 	bss->llg_coexist = bss_v0.llg_coexist;
1718 	bss->ht20_coexist = bss_v0.ht20_coexist;
1719 	bss->lln_non_gf_coexist = bss_v0.lln_non_gf_coexist;
1720 
1721 	bss->lsig_tx_op_protection_full_support =
1722 		bss_v0.lsig_tx_op_protection_full_support;
1723 	bss->rifs_mode = bss_v0.rifs_mode;
1724 	bss->beacon_interval = bss_v0.beacon_interval;
1725 	bss->dtim_period = bss_v0.dtim_period;
1726 	bss->tx_channel_width_set = bss_v0.tx_channel_width_set;
1727 	bss->oper_channel = bss_v0.oper_channel;
1728 
1729 	if (wcn->hw->conf.chandef.width == NL80211_CHAN_WIDTH_80) {
1730 		chandef = &wcn->hw->conf.chandef;
1731 		bss->ext_channel = HW_VALUE_PHY(chandef->chan->hw_value);
1732 	} else {
1733 		bss->ext_channel = bss_v0.ext_channel;
1734 	}
1735 
1736 	bss->reserved = bss_v0.reserved;
1737 
1738 	memcpy(&bss->ssid, &bss_v0.ssid,
1739 	       sizeof(bss_v0.ssid));
1740 
1741 	bss->action = bss_v0.action;
1742 	bss->rateset = bss_v0.rateset;
1743 	bss->ht = bss_v0.ht;
1744 	bss->obss_prot_enabled = bss_v0.obss_prot_enabled;
1745 	bss->rmf = bss_v0.rmf;
1746 	bss->ht_oper_mode = bss_v0.ht_oper_mode;
1747 	bss->dual_cts_protection = bss_v0.dual_cts_protection;
1748 
1749 	bss->max_probe_resp_retry_limit =
1750 		bss_v0.max_probe_resp_retry_limit;
1751 	bss->hidden_ssid = bss_v0.hidden_ssid;
1752 	bss->proxy_probe_resp =	bss_v0.proxy_probe_resp;
1753 	bss->edca_params_valid = bss_v0.edca_params_valid;
1754 
1755 	memcpy(&bss->acbe, &bss_v0.acbe,
1756 	       sizeof(bss_v0.acbe));
1757 	memcpy(&bss->acbk, &bss_v0.acbk,
1758 	       sizeof(bss_v0.acbk));
1759 	memcpy(&bss->acvi, &bss_v0.acvi,
1760 	       sizeof(bss_v0.acvi));
1761 	memcpy(&bss->acvo, &bss_v0.acvo,
1762 	       sizeof(bss_v0.acvo));
1763 
1764 	bss->ext_set_sta_key_param_valid =
1765 		bss_v0.ext_set_sta_key_param_valid;
1766 
1767 	memcpy(&bss->ext_set_sta_key_param,
1768 	       &bss_v0.ext_set_sta_key_param,
1769 	       sizeof(bss_v0.acvo));
1770 
1771 	bss->wcn36xx_hal_persona = bss_v0.wcn36xx_hal_persona;
1772 	bss->spectrum_mgt_enable = bss_v0.spectrum_mgt_enable;
1773 	bss->tx_mgmt_power = bss_v0.tx_mgmt_power;
1774 	bss->max_tx_power = bss_v0.max_tx_power;
1775 
1776 	wcn36xx_smd_set_bss_vht_params(vif, sta_80211, bss);
1777 
1778 	PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
1779 
1780 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1781 		    "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1782 		    bss->bssid, bss->self_mac_addr, bss->bss_type,
1783 		    bss->oper_mode, bss->nw_type);
1784 
1785 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1786 		    "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1787 		    sta->bssid, sta->action, sta->sta_index,
1788 		    sta->bssid_index, sta->aid, sta->type, sta->mac);
1789 
1790 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
1791 	kfree(msg_body);
1792 
1793 	return ret;
1794 }
1795 
1796 static int wcn36xx_smd_config_bss_v0(struct wcn36xx *wcn,
1797 				     struct ieee80211_vif *vif,
1798 				     struct ieee80211_sta *sta,
1799 				     const u8 *bssid,
1800 				     bool update)
1801 {
1802 	struct wcn36xx_hal_config_bss_req_msg *msg;
1803 	struct wcn36xx_hal_config_bss_params *bss;
1804 	struct wcn36xx_hal_config_sta_params *sta_params;
1805 	int ret;
1806 
1807 	msg = kzalloc(sizeof(*msg), GFP_KERNEL);
1808 	if (!msg)
1809 		return -ENOMEM;
1810 
1811 	INIT_HAL_MSG((*msg), WCN36XX_HAL_CONFIG_BSS_REQ);
1812 
1813 	bss = &msg->bss_params;
1814 	sta_params = &bss->sta;
1815 
1816 	wcn36xx_smd_set_bss_params(wcn, vif, sta, bssid, update, bss);
1817 	wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1818 
1819 	PREPARE_HAL_BUF(wcn->hal_buf, (*msg));
1820 
1821 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1822 		    "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1823 		    bss->bssid, bss->self_mac_addr, bss->bss_type,
1824 		    bss->oper_mode, bss->nw_type);
1825 
1826 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1827 		    "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1828 		    sta_params->bssid, sta_params->action,
1829 		    sta_params->sta_index, sta_params->bssid_index,
1830 		    sta_params->aid, sta_params->type,
1831 		    sta_params->mac);
1832 
1833 	ret = wcn36xx_smd_send_and_wait(wcn, msg->header.len);
1834 	kfree(msg);
1835 
1836 	return ret;
1837 }
1838 
1839 static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
1840 				      struct ieee80211_vif *vif,
1841 				      struct ieee80211_sta *sta,
1842 				      void *buf,
1843 				      size_t len)
1844 {
1845 	struct wcn36xx_hal_config_bss_rsp_msg *rsp;
1846 	struct wcn36xx_hal_config_bss_rsp_params *params;
1847 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1848 
1849 	if (len < sizeof(*rsp))
1850 		return -EINVAL;
1851 
1852 	rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf;
1853 	params = &rsp->bss_rsp_params;
1854 
1855 	if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1856 		wcn36xx_warn("hal config bss response failure: %d\n",
1857 			     params->status);
1858 		return -EIO;
1859 	}
1860 
1861 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1862 		    "hal config bss rsp status %d bss_idx %d dpu_desc_index %d"
1863 		    " sta_idx %d self_idx %d bcast_idx %d mac %pM"
1864 		    " power %d ucast_dpu_signature %d\n",
1865 		    params->status, params->bss_index, params->dpu_desc_index,
1866 		    params->bss_sta_index, params->bss_self_sta_index,
1867 		    params->bss_bcast_sta_idx, params->mac,
1868 		    params->tx_mgmt_power, params->ucast_dpu_signature);
1869 
1870 	vif_priv->bss_index = params->bss_index;
1871 
1872 	if (sta) {
1873 		struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1874 		sta_priv->bss_sta_index = params->bss_sta_index;
1875 		sta_priv->bss_dpu_desc_index = params->dpu_desc_index;
1876 	}
1877 
1878 	vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature;
1879 
1880 	return 0;
1881 }
1882 
1883 int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1884 			   struct ieee80211_sta *sta, const u8 *bssid,
1885 			   bool update)
1886 {
1887 	int ret;
1888 
1889 	mutex_lock(&wcn->hal_mutex);
1890 
1891 	if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24))
1892 		ret = wcn36xx_smd_config_bss_v1(wcn, vif, sta, bssid, update);
1893 	else
1894 		ret = wcn36xx_smd_config_bss_v0(wcn, vif, sta, bssid, update);
1895 
1896 	if (ret) {
1897 		wcn36xx_err("Sending hal_config_bss failed\n");
1898 		goto out;
1899 	}
1900 	ret = wcn36xx_smd_config_bss_rsp(wcn,
1901 					 vif,
1902 					 sta,
1903 					 wcn->hal_buf,
1904 					 wcn->hal_rsp_len);
1905 	if (ret)
1906 		wcn36xx_err("hal_config_bss response failed err=%d\n", ret);
1907 
1908 out:
1909 	mutex_unlock(&wcn->hal_mutex);
1910 	return ret;
1911 }
1912 
1913 int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1914 {
1915 	struct wcn36xx_hal_delete_bss_req_msg msg_body;
1916 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1917 	int ret = 0;
1918 
1919 	mutex_lock(&wcn->hal_mutex);
1920 
1921 	if (vif_priv->bss_index == WCN36XX_HAL_BSS_INVALID_IDX)
1922 		goto out;
1923 
1924 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ);
1925 
1926 	msg_body.bss_index = vif_priv->bss_index;
1927 
1928 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1929 
1930 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index);
1931 
1932 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1933 	if (ret) {
1934 		wcn36xx_err("Sending hal_delete_bss failed\n");
1935 		goto out;
1936 	}
1937 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1938 	if (ret) {
1939 		wcn36xx_err("hal_delete_bss response failed err=%d\n", ret);
1940 		goto out;
1941 	}
1942 
1943 	vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
1944 out:
1945 	mutex_unlock(&wcn->hal_mutex);
1946 	return ret;
1947 }
1948 
1949 int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1950 			    struct sk_buff *skb_beacon, u16 tim_off,
1951 			    u16 p2p_off)
1952 {
1953 	struct wcn36xx_hal_send_beacon_req_msg msg_body;
1954 	int ret, pad, pvm_len;
1955 
1956 	mutex_lock(&wcn->hal_mutex);
1957 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
1958 
1959 	pvm_len = skb_beacon->data[tim_off + 1] - 3;
1960 	pad = TIM_MIN_PVM_SIZE - pvm_len;
1961 
1962 	/* Padding is irrelevant to mesh mode since tim_off is always 0. */
1963 	if (vif->type == NL80211_IFTYPE_MESH_POINT)
1964 		pad = 0;
1965 
1966 	msg_body.beacon_length = skb_beacon->len + pad;
1967 	/* TODO need to find out why + 6 is needed */
1968 	msg_body.beacon_length6 = msg_body.beacon_length + 6;
1969 
1970 	if (msg_body.beacon_length > BEACON_TEMPLATE_SIZE) {
1971 		wcn36xx_err("Beacon is too big: beacon size=%d\n",
1972 			      msg_body.beacon_length);
1973 		ret = -ENOMEM;
1974 		goto out;
1975 	}
1976 	memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len);
1977 	memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
1978 
1979 	if (pad > 0) {
1980 		/*
1981 		 * The wcn36xx FW has a fixed size for the PVM in the TIM. If
1982 		 * given the beacon template from mac80211 with a PVM shorter
1983 		 * than the FW expectes it will overwrite the data after the
1984 		 * TIM.
1985 		 */
1986 		wcn36xx_dbg(WCN36XX_DBG_HAL, "Pad TIM PVM. %d bytes at %d\n",
1987 			    pad, pvm_len);
1988 		memmove(&msg_body.beacon[tim_off + 5 + pvm_len + pad],
1989 			&msg_body.beacon[tim_off + 5 + pvm_len],
1990 			skb_beacon->len - (tim_off + 5 + pvm_len));
1991 		memset(&msg_body.beacon[tim_off + 5 + pvm_len], 0, pad);
1992 		msg_body.beacon[tim_off + 1] += pad;
1993 	}
1994 
1995 	/* TODO need to find out why this is needed? */
1996 	if (vif->type == NL80211_IFTYPE_MESH_POINT)
1997 		/* mesh beacon don't need this, so push further down */
1998 		msg_body.tim_ie_offset = 256;
1999 	else
2000 		msg_body.tim_ie_offset = tim_off+4;
2001 	msg_body.p2p_ie_offset = p2p_off;
2002 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2003 
2004 	wcn36xx_dbg(WCN36XX_DBG_HAL,
2005 		    "hal send beacon beacon_length %d\n",
2006 		    msg_body.beacon_length);
2007 
2008 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2009 	if (ret) {
2010 		wcn36xx_err("Sending hal_send_beacon failed\n");
2011 		goto out;
2012 	}
2013 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2014 	if (ret) {
2015 		wcn36xx_err("hal_send_beacon response failed err=%d\n", ret);
2016 		goto out;
2017 	}
2018 out:
2019 	mutex_unlock(&wcn->hal_mutex);
2020 	return ret;
2021 }
2022 
2023 int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn,
2024 				      struct ieee80211_vif *vif,
2025 				      struct sk_buff *skb)
2026 {
2027 	struct wcn36xx_hal_send_probe_resp_req_msg msg;
2028 	int ret;
2029 
2030 	mutex_lock(&wcn->hal_mutex);
2031 	INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ);
2032 
2033 	if (skb->len > BEACON_TEMPLATE_SIZE) {
2034 		wcn36xx_warn("probe response template is too big: %d\n",
2035 			     skb->len);
2036 		ret = -E2BIG;
2037 		goto out;
2038 	}
2039 
2040 	msg.probe_resp_template_len = skb->len;
2041 	memcpy(&msg.probe_resp_template, skb->data, skb->len);
2042 
2043 	memcpy(msg.bssid, vif->addr, ETH_ALEN);
2044 
2045 	PREPARE_HAL_BUF(wcn->hal_buf, msg);
2046 
2047 	wcn36xx_dbg(WCN36XX_DBG_HAL,
2048 		    "hal update probe rsp len %d bssid %pM\n",
2049 		    msg.probe_resp_template_len, msg.bssid);
2050 
2051 	ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
2052 	if (ret) {
2053 		wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n");
2054 		goto out;
2055 	}
2056 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2057 	if (ret) {
2058 		wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n",
2059 			    ret);
2060 		goto out;
2061 	}
2062 out:
2063 	mutex_unlock(&wcn->hal_mutex);
2064 	return ret;
2065 }
2066 
2067 int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
2068 			   enum ani_ed_type enc_type,
2069 			   u8 keyidx,
2070 			   u8 keylen,
2071 			   u8 *key,
2072 			   u8 sta_index)
2073 {
2074 	struct wcn36xx_hal_set_sta_key_req_msg msg_body;
2075 	int ret;
2076 
2077 	mutex_lock(&wcn->hal_mutex);
2078 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ);
2079 
2080 	msg_body.set_sta_key_params.sta_index = sta_index;
2081 	msg_body.set_sta_key_params.enc_type = enc_type;
2082 
2083 	if (enc_type == WCN36XX_HAL_ED_WEP104 ||
2084 	    enc_type == WCN36XX_HAL_ED_WEP40) {
2085 		/* Use bss key for wep (static) */
2086 		msg_body.set_sta_key_params.def_wep_idx = keyidx;
2087 		msg_body.set_sta_key_params.wep_type = 0;
2088 	} else {
2089 		msg_body.set_sta_key_params.key[0].id = keyidx;
2090 		msg_body.set_sta_key_params.key[0].unicast = 1;
2091 		msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
2092 		msg_body.set_sta_key_params.key[0].pae_role = 0;
2093 		msg_body.set_sta_key_params.key[0].length = keylen;
2094 		memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
2095 	}
2096 
2097 	msg_body.set_sta_key_params.single_tid_rc = 1;
2098 
2099 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2100 
2101 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2102 	if (ret) {
2103 		wcn36xx_err("Sending hal_set_stakey failed\n");
2104 		goto out;
2105 	}
2106 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2107 	if (ret) {
2108 		wcn36xx_err("hal_set_stakey response failed err=%d\n", ret);
2109 		goto out;
2110 	}
2111 out:
2112 	mutex_unlock(&wcn->hal_mutex);
2113 	return ret;
2114 }
2115 
2116 int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn,
2117 			   enum ani_ed_type enc_type,
2118 			   u8 bssidx,
2119 			   u8 keyidx,
2120 			   u8 keylen,
2121 			   u8 *key)
2122 {
2123 	struct wcn36xx_hal_set_bss_key_req_msg msg_body;
2124 	int ret;
2125 
2126 	mutex_lock(&wcn->hal_mutex);
2127 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ);
2128 	msg_body.bss_idx = bssidx;
2129 	msg_body.enc_type = enc_type;
2130 	msg_body.num_keys = 1;
2131 	msg_body.keys[0].id = keyidx;
2132 	msg_body.keys[0].unicast = 0;
2133 	msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY;
2134 	msg_body.keys[0].pae_role = 0;
2135 	msg_body.keys[0].length = keylen;
2136 	memcpy(msg_body.keys[0].key, key, keylen);
2137 
2138 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2139 
2140 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2141 	if (ret) {
2142 		wcn36xx_err("Sending hal_set_bsskey failed\n");
2143 		goto out;
2144 	}
2145 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2146 	if (ret) {
2147 		wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret);
2148 		goto out;
2149 	}
2150 out:
2151 	mutex_unlock(&wcn->hal_mutex);
2152 	return ret;
2153 }
2154 
2155 int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn,
2156 			      enum ani_ed_type enc_type,
2157 			      u8 keyidx,
2158 			      u8 sta_index)
2159 {
2160 	struct wcn36xx_hal_remove_sta_key_req_msg msg_body;
2161 	int ret;
2162 
2163 	mutex_lock(&wcn->hal_mutex);
2164 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ);
2165 
2166 	msg_body.sta_idx = sta_index;
2167 	msg_body.enc_type = enc_type;
2168 	msg_body.key_id = keyidx;
2169 
2170 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2171 
2172 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2173 	if (ret) {
2174 		wcn36xx_err("Sending hal_remove_stakey failed\n");
2175 		goto out;
2176 	}
2177 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2178 	if (ret) {
2179 		wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret);
2180 		goto out;
2181 	}
2182 out:
2183 	mutex_unlock(&wcn->hal_mutex);
2184 	return ret;
2185 }
2186 
2187 int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
2188 			      enum ani_ed_type enc_type,
2189 			      u8 bssidx,
2190 			      u8 keyidx)
2191 {
2192 	struct wcn36xx_hal_remove_bss_key_req_msg msg_body;
2193 	int ret;
2194 
2195 	mutex_lock(&wcn->hal_mutex);
2196 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ);
2197 	msg_body.bss_idx = bssidx;
2198 	msg_body.enc_type = enc_type;
2199 	msg_body.key_id = keyidx;
2200 
2201 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2202 
2203 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2204 	if (ret) {
2205 		wcn36xx_err("Sending hal_remove_bsskey failed\n");
2206 		goto out;
2207 	}
2208 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2209 	if (ret) {
2210 		wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
2211 		goto out;
2212 	}
2213 out:
2214 	mutex_unlock(&wcn->hal_mutex);
2215 	return ret;
2216 }
2217 
2218 int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
2219 {
2220 	struct wcn36xx_hal_enter_bmps_req_msg msg_body;
2221 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2222 	int ret;
2223 
2224 	mutex_lock(&wcn->hal_mutex);
2225 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ);
2226 
2227 	msg_body.bss_index = vif_priv->bss_index;
2228 	msg_body.tbtt = vif->bss_conf.sync_tsf;
2229 	msg_body.dtim_period = vif_priv->dtim_period;
2230 
2231 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2232 
2233 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2234 	if (ret) {
2235 		wcn36xx_err("Sending hal_enter_bmps failed\n");
2236 		goto out;
2237 	}
2238 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2239 	if (ret) {
2240 		wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret);
2241 		goto out;
2242 	}
2243 out:
2244 	mutex_unlock(&wcn->hal_mutex);
2245 	return ret;
2246 }
2247 
2248 int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
2249 {
2250 	struct wcn36xx_hal_exit_bmps_req_msg msg_body;
2251 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2252 	int ret;
2253 
2254 	mutex_lock(&wcn->hal_mutex);
2255 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ);
2256 
2257 	msg_body.bss_index = vif_priv->bss_index;
2258 	msg_body.send_data_null = 1;
2259 
2260 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2261 
2262 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2263 	if (ret) {
2264 		wcn36xx_err("Sending hal_exit_bmps failed\n");
2265 		goto out;
2266 	}
2267 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2268 	if (ret) {
2269 		wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
2270 		goto out;
2271 	}
2272 out:
2273 	mutex_unlock(&wcn->hal_mutex);
2274 	return ret;
2275 }
2276 
2277 int wcn36xx_smd_enter_imps(struct wcn36xx *wcn)
2278 {
2279 	struct wcn36xx_hal_enter_imps_req_msg msg_body;
2280 	int ret;
2281 
2282 	mutex_lock(&wcn->hal_mutex);
2283 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_IMPS_REQ);
2284 
2285 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2286 
2287 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2288 	if (ret) {
2289 		wcn36xx_err("Sending hal_enter_imps failed\n");
2290 		goto out;
2291 	}
2292 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2293 	if (ret) {
2294 		wcn36xx_err("hal_enter_imps response failed err=%d\n", ret);
2295 		goto out;
2296 	}
2297 
2298 	wcn36xx_dbg(WCN36XX_DBG_HAL, "Entered idle mode\n");
2299 out:
2300 	mutex_unlock(&wcn->hal_mutex);
2301 	return ret;
2302 }
2303 
2304 int wcn36xx_smd_exit_imps(struct wcn36xx *wcn)
2305 {
2306 	struct wcn36xx_hal_exit_imps_req_msg msg_body;
2307 	int ret;
2308 
2309 	mutex_lock(&wcn->hal_mutex);
2310 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_IMPS_REQ);
2311 
2312 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2313 
2314 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2315 	if (ret) {
2316 		wcn36xx_err("Sending hal_exit_imps failed\n");
2317 		goto out;
2318 	}
2319 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2320 	if (ret) {
2321 		wcn36xx_err("hal_exit_imps response failed err=%d\n", ret);
2322 		goto out;
2323 	}
2324 	wcn36xx_dbg(WCN36XX_DBG_HAL, "Exited idle mode\n");
2325 out:
2326 	mutex_unlock(&wcn->hal_mutex);
2327 	return ret;
2328 }
2329 
2330 int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim)
2331 {
2332 	struct wcn36xx_hal_set_power_params_req_msg msg_body;
2333 	int ret;
2334 
2335 	mutex_lock(&wcn->hal_mutex);
2336 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ);
2337 
2338 	/*
2339 	 * When host is down ignore every second dtim
2340 	 */
2341 	if (ignore_dtim) {
2342 		msg_body.ignore_dtim = 1;
2343 		msg_body.dtim_period = 2;
2344 	}
2345 	msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
2346 
2347 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2348 
2349 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2350 	if (ret) {
2351 		wcn36xx_err("Sending hal_set_power_params failed\n");
2352 		goto out;
2353 	}
2354 
2355 out:
2356 	mutex_unlock(&wcn->hal_mutex);
2357 	return ret;
2358 }
2359 
2360 /* Notice: This function should be called after associated, or else it
2361  * will be invalid
2362  */
2363 int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
2364 			       struct ieee80211_vif *vif,
2365 			       int packet_type)
2366 {
2367 	struct wcn36xx_hal_keep_alive_req_msg msg_body;
2368 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2369 	int ret;
2370 
2371 	mutex_lock(&wcn->hal_mutex);
2372 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ);
2373 
2374 	if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) {
2375 		msg_body.bss_index = vif_priv->bss_index;
2376 		msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT;
2377 		msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD;
2378 	} else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) {
2379 		/* TODO: it also support ARP response type */
2380 	} else {
2381 		wcn36xx_warn("unknown keep alive packet type %d\n", packet_type);
2382 		ret = -EINVAL;
2383 		goto out;
2384 	}
2385 
2386 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2387 
2388 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2389 	if (ret) {
2390 		wcn36xx_err("Sending hal_keep_alive failed\n");
2391 		goto out;
2392 	}
2393 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2394 	if (ret) {
2395 		wcn36xx_err("hal_keep_alive response failed err=%d\n", ret);
2396 		goto out;
2397 	}
2398 out:
2399 	mutex_unlock(&wcn->hal_mutex);
2400 	return ret;
2401 }
2402 
2403 int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
2404 			     u32 arg3, u32 arg4, u32 arg5)
2405 {
2406 	struct wcn36xx_hal_dump_cmd_req_msg msg_body;
2407 	int ret;
2408 
2409 	mutex_lock(&wcn->hal_mutex);
2410 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ);
2411 
2412 	msg_body.arg1 = arg1;
2413 	msg_body.arg2 = arg2;
2414 	msg_body.arg3 = arg3;
2415 	msg_body.arg4 = arg4;
2416 	msg_body.arg5 = arg5;
2417 
2418 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2419 
2420 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2421 	if (ret) {
2422 		wcn36xx_err("Sending hal_dump_cmd failed\n");
2423 		goto out;
2424 	}
2425 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2426 	if (ret) {
2427 		wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret);
2428 		goto out;
2429 	}
2430 out:
2431 	mutex_unlock(&wcn->hal_mutex);
2432 	return ret;
2433 }
2434 
2435 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
2436 {
2437 	struct wcn36xx_hal_feat_caps_msg msg_body, *rsp;
2438 	int ret, i;
2439 
2440 	mutex_lock(&wcn->hal_mutex);
2441 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
2442 
2443 	wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
2444 	if (wcn->rf_id == RF_IRIS_WCN3680) {
2445 		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, DOT11AC);
2446 		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, WLAN_CH144);
2447 		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps,
2448 					       ANTENNA_DIVERSITY_SELECTION);
2449 	}
2450 
2451 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2452 
2453 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2454 	if (ret) {
2455 		wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
2456 		goto out;
2457 	}
2458 	if (wcn->hal_rsp_len != sizeof(*rsp)) {
2459 		wcn36xx_err("Invalid hal_feature_caps_exchange response");
2460 		goto out;
2461 	}
2462 
2463 	rsp = (struct wcn36xx_hal_feat_caps_msg *) wcn->hal_buf;
2464 
2465 	for (i = 0; i < WCN36XX_HAL_CAPS_SIZE; i++)
2466 		wcn->fw_feat_caps[i] = rsp->feat_caps[i];
2467 out:
2468 	mutex_unlock(&wcn->hal_mutex);
2469 	return ret;
2470 }
2471 
2472 static int wcn36xx_smd_add_ba_session_rsp(void *buf, int len, u8 *session)
2473 {
2474 	struct wcn36xx_hal_add_ba_session_rsp_msg *rsp;
2475 
2476 	if (len < sizeof(*rsp))
2477 		return -EINVAL;
2478 
2479 	rsp = (struct wcn36xx_hal_add_ba_session_rsp_msg *)buf;
2480 	if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS)
2481 		return rsp->status;
2482 
2483 	*session = rsp->ba_session_id;
2484 
2485 	return 0;
2486 }
2487 
2488 int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
2489 		struct ieee80211_sta *sta,
2490 		u16 tid,
2491 		u16 *ssn,
2492 		u8 direction,
2493 		u8 sta_index)
2494 {
2495 	struct wcn36xx_hal_add_ba_session_req_msg msg_body;
2496 	u8 session_id;
2497 	int ret;
2498 
2499 	mutex_lock(&wcn->hal_mutex);
2500 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ);
2501 
2502 	msg_body.sta_index = sta_index;
2503 	memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN);
2504 	msg_body.dialog_token = 0x10;
2505 	msg_body.tid = tid;
2506 
2507 	/* Immediate BA because Delayed BA is not supported */
2508 	msg_body.policy = 1;
2509 	msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE;
2510 	msg_body.timeout = 0;
2511 	if (ssn)
2512 		msg_body.ssn = *ssn;
2513 	msg_body.direction = direction;
2514 
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_add_ba_session failed\n");
2520 		goto out;
2521 	}
2522 	ret = wcn36xx_smd_add_ba_session_rsp(wcn->hal_buf, wcn->hal_rsp_len,
2523 					     &session_id);
2524 	if (ret) {
2525 		wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret);
2526 		ret = -EINVAL;
2527 		goto out;
2528 	}
2529 
2530 	ret = session_id;
2531 out:
2532 	mutex_unlock(&wcn->hal_mutex);
2533 	return ret;
2534 }
2535 
2536 int wcn36xx_smd_add_ba(struct wcn36xx *wcn, u8 session_id)
2537 {
2538 	struct wcn36xx_hal_add_ba_req_msg msg_body;
2539 	int ret;
2540 
2541 	mutex_lock(&wcn->hal_mutex);
2542 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ);
2543 
2544 	msg_body.session_id = session_id;
2545 	msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE;
2546 
2547 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2548 
2549 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2550 	if (ret) {
2551 		wcn36xx_err("Sending hal_add_ba failed\n");
2552 		goto out;
2553 	}
2554 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2555 	if (ret) {
2556 		wcn36xx_err("hal_add_ba response failed err=%d\n", ret);
2557 		goto out;
2558 	}
2559 out:
2560 	mutex_unlock(&wcn->hal_mutex);
2561 	return ret;
2562 }
2563 
2564 int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 direction, u8 sta_index)
2565 {
2566 	struct wcn36xx_hal_del_ba_req_msg msg_body;
2567 	int ret;
2568 
2569 	mutex_lock(&wcn->hal_mutex);
2570 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ);
2571 
2572 	msg_body.sta_index = sta_index;
2573 	msg_body.tid = tid;
2574 	msg_body.direction = direction;
2575 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2576 
2577 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2578 	if (ret) {
2579 		wcn36xx_err("Sending hal_del_ba failed\n");
2580 		goto out;
2581 	}
2582 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2583 	if (ret) {
2584 		wcn36xx_err("hal_del_ba response failed err=%d\n", ret);
2585 		goto out;
2586 	}
2587 out:
2588 	mutex_unlock(&wcn->hal_mutex);
2589 	return ret;
2590 }
2591 
2592 int wcn36xx_smd_get_stats(struct wcn36xx *wcn, u8 sta_index, u32 stats_mask,
2593 			  struct station_info *sinfo)
2594 {
2595 	struct wcn36xx_hal_stats_req_msg msg_body;
2596 	struct wcn36xx_hal_stats_rsp_msg *rsp;
2597 	void *rsp_body;
2598 	int ret;
2599 
2600 	if (stats_mask & ~HAL_GLOBAL_CLASS_A_STATS_INFO) {
2601 		wcn36xx_err("stats_mask 0x%x contains unimplemented types\n",
2602 			    stats_mask);
2603 		return -EINVAL;
2604 	}
2605 
2606 	mutex_lock(&wcn->hal_mutex);
2607 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_GET_STATS_REQ);
2608 
2609 	msg_body.sta_id = sta_index;
2610 	msg_body.stats_mask = stats_mask;
2611 
2612 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2613 
2614 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2615 	if (ret) {
2616 		wcn36xx_err("sending hal_get_stats failed\n");
2617 		goto out;
2618 	}
2619 
2620 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2621 	if (ret) {
2622 		wcn36xx_err("hal_get_stats response failed err=%d\n", ret);
2623 		goto out;
2624 	}
2625 
2626 	rsp = (struct wcn36xx_hal_stats_rsp_msg *)wcn->hal_buf;
2627 	rsp_body = (wcn->hal_buf + sizeof(struct wcn36xx_hal_stats_rsp_msg));
2628 
2629 	if (rsp->stats_mask != stats_mask) {
2630 		wcn36xx_err("stats_mask 0x%x differs from requested 0x%x\n",
2631 			    rsp->stats_mask, stats_mask);
2632 		goto out;
2633 	}
2634 
2635 	if (rsp->stats_mask & HAL_GLOBAL_CLASS_A_STATS_INFO) {
2636 		struct ani_global_class_a_stats_info *stats_info = rsp_body;
2637 
2638 		wcn36xx_process_tx_rate(stats_info, &sinfo->txrate);
2639 		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
2640 		rsp_body += sizeof(struct ani_global_class_a_stats_info);
2641 	}
2642 out:
2643 	mutex_unlock(&wcn->hal_mutex);
2644 
2645 	return ret;
2646 }
2647 
2648 static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len, struct add_ba_info *ba_info)
2649 {
2650 	struct wcn36xx_hal_trigger_ba_rsp_candidate *candidate;
2651 	struct wcn36xx_hal_trigger_ba_rsp_msg *rsp;
2652 	int i;
2653 
2654 	if (len < sizeof(*rsp))
2655 		return -EINVAL;
2656 
2657 	rsp = (struct wcn36xx_hal_trigger_ba_rsp_msg *) buf;
2658 
2659 	if (rsp->candidate_cnt < 1)
2660 		return rsp->status ? rsp->status : -EINVAL;
2661 
2662 	candidate = (struct wcn36xx_hal_trigger_ba_rsp_candidate *)(buf + sizeof(*rsp));
2663 
2664 	for (i = 0; i < STACFG_MAX_TC; i++) {
2665 		ba_info[i] = candidate->ba_info[i];
2666 	}
2667 
2668 	return rsp->status;
2669 }
2670 
2671 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u16 *ssn)
2672 {
2673 	struct wcn36xx_hal_trigger_ba_req_msg msg_body;
2674 	struct wcn36xx_hal_trigger_ba_req_candidate *candidate;
2675 	struct add_ba_info ba_info[STACFG_MAX_TC];
2676 	int ret;
2677 
2678 	if (tid >= STACFG_MAX_TC)
2679 		return -EINVAL;
2680 
2681 	mutex_lock(&wcn->hal_mutex);
2682 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
2683 
2684 	msg_body.session_id = 0; /* not really used */
2685 	msg_body.candidate_cnt = 1;
2686 	msg_body.header.len += sizeof(*candidate);
2687 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2688 
2689 	candidate = (struct wcn36xx_hal_trigger_ba_req_candidate *)
2690 		(wcn->hal_buf + sizeof(msg_body));
2691 	candidate->sta_index = sta_index;
2692 	candidate->tid_bitmap = 1 << tid;
2693 
2694 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2695 	if (ret) {
2696 		wcn36xx_err("Sending hal_trigger_ba failed\n");
2697 		goto out;
2698 	}
2699 	ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len, ba_info);
2700 	if (ret) {
2701 		wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
2702 		goto out;
2703 	}
2704 out:
2705 	mutex_unlock(&wcn->hal_mutex);
2706 
2707 	if (ssn)
2708 		*ssn = ba_info[tid].starting_seq_num;
2709 
2710 	return ret;
2711 }
2712 
2713 static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len)
2714 {
2715 	struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf;
2716 
2717 	if (len != sizeof(*rsp)) {
2718 		wcn36xx_warn("Bad TX complete indication\n");
2719 		return -EIO;
2720 	}
2721 
2722 	wcn36xx_dxe_tx_ack_ind(wcn, rsp->status);
2723 
2724 	return 0;
2725 }
2726 
2727 static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, void *buf, size_t len)
2728 {
2729 	struct wcn36xx_hal_scan_offload_ind *rsp = buf;
2730 	struct cfg80211_scan_info scan_info = {};
2731 
2732 	if (len != sizeof(*rsp)) {
2733 		wcn36xx_warn("Corrupted delete scan indication\n");
2734 		return -EIO;
2735 	}
2736 
2737 	wcn36xx_dbg(WCN36XX_DBG_HAL, "scan indication (type %x)\n", rsp->type);
2738 
2739 	switch (rsp->type) {
2740 	case WCN36XX_HAL_SCAN_IND_FAILED:
2741 	case WCN36XX_HAL_SCAN_IND_DEQUEUED:
2742 		scan_info.aborted = true;
2743 		fallthrough;
2744 	case WCN36XX_HAL_SCAN_IND_COMPLETED:
2745 		mutex_lock(&wcn->scan_lock);
2746 		wcn->scan_req = NULL;
2747 		if (wcn->scan_aborted)
2748 			scan_info.aborted = true;
2749 		mutex_unlock(&wcn->scan_lock);
2750 		ieee80211_scan_completed(wcn->hw, &scan_info);
2751 		break;
2752 	case WCN36XX_HAL_SCAN_IND_STARTED:
2753 	case WCN36XX_HAL_SCAN_IND_FOREIGN_CHANNEL:
2754 	case WCN36XX_HAL_SCAN_IND_PREEMPTED:
2755 	case WCN36XX_HAL_SCAN_IND_RESTARTED:
2756 		break;
2757 	default:
2758 		wcn36xx_warn("Unknown scan indication type %x\n", rsp->type);
2759 	}
2760 
2761 	return 0;
2762 }
2763 
2764 static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
2765 					 void *buf,
2766 					 size_t len)
2767 {
2768 	struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf;
2769 	struct ieee80211_vif *vif = NULL;
2770 	struct wcn36xx_vif *tmp;
2771 
2772 	/* Old FW does not have bss index */
2773 	if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
2774 		list_for_each_entry(tmp, &wcn->vif_list, list) {
2775 			wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2776 				    tmp->bss_index);
2777 			vif = wcn36xx_priv_to_vif(tmp);
2778 			ieee80211_beacon_loss(vif);
2779 		}
2780 		return 0;
2781 	}
2782 
2783 	if (len != sizeof(*rsp)) {
2784 		wcn36xx_warn("Corrupted missed beacon indication\n");
2785 		return -EIO;
2786 	}
2787 
2788 	list_for_each_entry(tmp, &wcn->vif_list, list) {
2789 		if (tmp->bss_index == rsp->bss_index) {
2790 			wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2791 				    rsp->bss_index);
2792 			vif = wcn36xx_priv_to_vif(tmp);
2793 			ieee80211_beacon_loss(vif);
2794 			return 0;
2795 		}
2796 	}
2797 
2798 	wcn36xx_warn("BSS index %d not found\n", rsp->bss_index);
2799 	return -ENOENT;
2800 }
2801 
2802 static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
2803 					      void *buf,
2804 					      size_t len)
2805 {
2806 	struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
2807 	struct wcn36xx_vif *vif_priv;
2808 	struct ieee80211_vif *vif;
2809 	struct ieee80211_bss_conf *bss_conf;
2810 	struct ieee80211_sta *sta;
2811 	bool found = false;
2812 
2813 	if (len != sizeof(*rsp)) {
2814 		wcn36xx_warn("Corrupted delete sta indication\n");
2815 		return -EIO;
2816 	}
2817 
2818 	wcn36xx_dbg(WCN36XX_DBG_HAL,
2819 		    "delete station indication %pM index %d reason %d\n",
2820 		    rsp->addr2, rsp->sta_id, rsp->reason_code);
2821 
2822 	list_for_each_entry(vif_priv, &wcn->vif_list, list) {
2823 		rcu_read_lock();
2824 		vif = wcn36xx_priv_to_vif(vif_priv);
2825 
2826 		if (vif->type == NL80211_IFTYPE_STATION) {
2827 			/* We could call ieee80211_find_sta too, but checking
2828 			 * bss_conf is clearer.
2829 			 */
2830 			bss_conf = &vif->bss_conf;
2831 			if (vif_priv->sta_assoc &&
2832 			    !memcmp(bss_conf->bssid, rsp->addr2, ETH_ALEN)) {
2833 				found = true;
2834 				wcn36xx_dbg(WCN36XX_DBG_HAL,
2835 					    "connection loss bss_index %d\n",
2836 					    vif_priv->bss_index);
2837 				ieee80211_connection_loss(vif);
2838 			}
2839 		} else {
2840 			sta = ieee80211_find_sta(vif, rsp->addr2);
2841 			if (sta) {
2842 				found = true;
2843 				ieee80211_report_low_ack(sta, 0);
2844 			}
2845 		}
2846 
2847 		rcu_read_unlock();
2848 		if (found)
2849 			return 0;
2850 	}
2851 
2852 	wcn36xx_warn("BSS or STA with addr %pM not found\n", rsp->addr2);
2853 	return -ENOENT;
2854 }
2855 
2856 static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn,
2857 					  void *buf,
2858 					  size_t len)
2859 {
2860 	struct wcn36xx_hal_print_reg_info_ind *rsp = buf;
2861 	int i;
2862 
2863 	if (len < sizeof(*rsp)) {
2864 		wcn36xx_warn("Corrupted print reg info indication\n");
2865 		return -EIO;
2866 	}
2867 
2868 	wcn36xx_dbg(WCN36XX_DBG_HAL,
2869 		    "reginfo indication, scenario: 0x%x reason: 0x%x\n",
2870 		    rsp->scenario, rsp->reason);
2871 
2872 	for (i = 0; i < rsp->count; i++) {
2873 		wcn36xx_dbg(WCN36XX_DBG_HAL, "\t0x%x: 0x%x\n",
2874 			    rsp->regs[i].addr, rsp->regs[i].value);
2875 	}
2876 
2877 	return 0;
2878 }
2879 
2880 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
2881 {
2882 	struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
2883 	size_t len;
2884 	int ret;
2885 
2886 	mutex_lock(&wcn->hal_mutex);
2887 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ);
2888 
2889 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2890 
2891 	body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf;
2892 	len = msg_body.header.len;
2893 
2894 	put_cfg_tlv_u32(wcn, &len, cfg_id, value);
2895 	body->header.len = len;
2896 	body->len = len - sizeof(*body);
2897 
2898 	ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
2899 	if (ret) {
2900 		wcn36xx_err("Sending hal_update_cfg failed\n");
2901 		goto out;
2902 	}
2903 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2904 	if (ret) {
2905 		wcn36xx_err("hal_update_cfg response failed err=%d\n", ret);
2906 		goto out;
2907 	}
2908 out:
2909 	mutex_unlock(&wcn->hal_mutex);
2910 	return ret;
2911 }
2912 
2913 int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
2914 			    struct ieee80211_vif *vif,
2915 			    struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp)
2916 {
2917 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2918 	struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *msg_body = NULL;
2919 	int ret;
2920 
2921 	mutex_lock(&wcn->hal_mutex);
2922 
2923 	msg_body = (struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *)
2924 		   wcn->hal_buf;
2925 	INIT_HAL_MSG(*msg_body, WCN36XX_HAL_8023_MULTICAST_LIST_REQ);
2926 
2927 	/* An empty list means all mc traffic will be received */
2928 	if (fp)
2929 		memcpy(&msg_body->mc_addr_list, fp,
2930 		       sizeof(msg_body->mc_addr_list));
2931 	else
2932 		msg_body->mc_addr_list.mc_addr_count = 0;
2933 
2934 	msg_body->mc_addr_list.bss_index = vif_priv->bss_index;
2935 
2936 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
2937 	if (ret) {
2938 		wcn36xx_err("Sending HAL_8023_MULTICAST_LIST failed\n");
2939 		goto out;
2940 	}
2941 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2942 	if (ret) {
2943 		wcn36xx_err("HAL_8023_MULTICAST_LIST rsp failed err=%d\n", ret);
2944 		goto out;
2945 	}
2946 out:
2947 	mutex_unlock(&wcn->hal_mutex);
2948 	return ret;
2949 }
2950 
2951 int wcn36xx_smd_arp_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
2952 			    bool enable)
2953 {
2954 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2955 	struct wcn36xx_hal_host_offload_req_msg msg_body;
2956 	int ret;
2957 
2958 	mutex_lock(&wcn->hal_mutex);
2959 
2960 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_OFFLOAD_REQ);
2961 	msg_body.host_offload_params.offload_type =
2962 		WCN36XX_HAL_IPV4_ARP_REPLY_OFFLOAD;
2963 	if (enable) {
2964 		msg_body.host_offload_params.enable =
2965 			WCN36XX_HAL_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
2966 		memcpy(&msg_body.host_offload_params.u,
2967 		       &vif->cfg.arp_addr_list[0], sizeof(__be32));
2968 	}
2969 	msg_body.ns_offload_params.bss_index = vif_priv->bss_index;
2970 
2971 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2972 
2973 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2974 	if (ret) {
2975 		wcn36xx_err("Sending host_offload_arp failed\n");
2976 		goto out;
2977 	}
2978 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2979 	if (ret) {
2980 		wcn36xx_err("host_offload_arp failed err=%d\n", ret);
2981 		goto out;
2982 	}
2983 out:
2984 	mutex_unlock(&wcn->hal_mutex);
2985 	return ret;
2986 }
2987 
2988 #if IS_ENABLED(CONFIG_IPV6)
2989 int wcn36xx_smd_ipv6_ns_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
2990 				bool enable)
2991 {
2992 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2993 	struct wcn36xx_hal_host_offload_req_msg msg_body;
2994 	struct wcn36xx_hal_ns_offload_params *ns_params;
2995 	struct wcn36xx_hal_host_offload_req *ho_params;
2996 	int ret;
2997 
2998 	mutex_lock(&wcn->hal_mutex);
2999 
3000 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_OFFLOAD_REQ);
3001 	ho_params = &msg_body.host_offload_params;
3002 	ns_params = &msg_body.ns_offload_params;
3003 
3004 	ho_params->offload_type = WCN36XX_HAL_IPV6_NS_OFFLOAD;
3005 	if (enable) {
3006 		ho_params->enable =
3007 			WCN36XX_HAL_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE;
3008 		if (vif_priv->num_target_ipv6_addrs) {
3009 			memcpy(&ho_params->u,
3010 			       &vif_priv->target_ipv6_addrs[0].in6_u,
3011 			       sizeof(struct in6_addr));
3012 			memcpy(&ns_params->target_ipv6_addr1,
3013 			       &vif_priv->target_ipv6_addrs[0].in6_u,
3014 			       sizeof(struct in6_addr));
3015 			ns_params->target_ipv6_addr1_valid = 1;
3016 		}
3017 		if (vif_priv->num_target_ipv6_addrs > 1) {
3018 			memcpy(&ns_params->target_ipv6_addr2,
3019 			       &vif_priv->target_ipv6_addrs[1].in6_u,
3020 			       sizeof(struct in6_addr));
3021 			ns_params->target_ipv6_addr2_valid = 1;
3022 		}
3023 	}
3024 	memcpy(&ns_params->self_addr, vif->addr, ETH_ALEN);
3025 	ns_params->bss_index = vif_priv->bss_index;
3026 
3027 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3028 
3029 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3030 	if (ret) {
3031 		wcn36xx_err("Sending host_offload_arp failed\n");
3032 		goto out;
3033 	}
3034 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3035 	if (ret) {
3036 		wcn36xx_err("host_offload_arp failed err=%d\n", ret);
3037 		goto out;
3038 	}
3039 out:
3040 	mutex_unlock(&wcn->hal_mutex);
3041 	return ret;
3042 }
3043 #else
3044 int wcn36xx_smd_ipv6_ns_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
3045 				bool enable)
3046 {
3047 	return 0;
3048 }
3049 #endif
3050 
3051 int wcn36xx_smd_gtk_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
3052 			    bool enable)
3053 {
3054 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3055 	struct wcn36xx_hal_gtk_offload_req_msg msg_body;
3056 	int ret;
3057 
3058 	mutex_lock(&wcn->hal_mutex);
3059 
3060 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_GTK_OFFLOAD_REQ);
3061 
3062 	if (enable) {
3063 		memcpy(&msg_body.kek, vif_priv->rekey_data.kek, NL80211_KEK_LEN);
3064 		memcpy(&msg_body.kck, vif_priv->rekey_data.kck, NL80211_KCK_LEN);
3065 		msg_body.key_replay_counter =
3066 			le64_to_cpu(vif_priv->rekey_data.replay_ctr);
3067 		msg_body.bss_index = vif_priv->bss_index;
3068 	} else {
3069 		msg_body.flags = WCN36XX_HAL_GTK_OFFLOAD_FLAGS_DISABLE;
3070 	}
3071 
3072 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3073 
3074 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3075 	if (ret) {
3076 		wcn36xx_err("Sending host_offload_arp failed\n");
3077 		goto out;
3078 	}
3079 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3080 	if (ret) {
3081 		wcn36xx_err("host_offload_arp failed err=%d\n", ret);
3082 		goto out;
3083 	}
3084 out:
3085 	mutex_unlock(&wcn->hal_mutex);
3086 	return ret;
3087 }
3088 
3089 static int wcn36xx_smd_gtk_offload_get_info_rsp(struct wcn36xx *wcn,
3090 						struct ieee80211_vif *vif)
3091 {
3092 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3093 	struct wcn36xx_hal_gtk_offload_get_info_rsp_msg *rsp;
3094 	__be64 replay_ctr;
3095 
3096 	if (wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len))
3097 		return -EIO;
3098 
3099 	rsp = (struct wcn36xx_hal_gtk_offload_get_info_rsp_msg *)wcn->hal_buf;
3100 
3101 	if (rsp->bss_index != vif_priv->bss_index) {
3102 		wcn36xx_err("gtk_offload_info invalid response bss index %d\n",
3103 			    rsp->bss_index);
3104 		return -ENOENT;
3105 	}
3106 
3107 	if (vif_priv->rekey_data.replay_ctr != cpu_to_le64(rsp->key_replay_counter)) {
3108 		replay_ctr = cpu_to_be64(rsp->key_replay_counter);
3109 		vif_priv->rekey_data.replay_ctr =
3110 			cpu_to_le64(rsp->key_replay_counter);
3111 		ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
3112 					   (void *)&replay_ctr, GFP_KERNEL);
3113 		wcn36xx_dbg(WCN36XX_DBG_HAL,
3114 			    "GTK replay counter increment %llu\n",
3115 			    rsp->key_replay_counter);
3116 	}
3117 
3118 	wcn36xx_dbg(WCN36XX_DBG_HAL,
3119 		    "gtk offload info status %d last_rekey_status %d "
3120 		    "replay_counter %llu total_rekey_count %d gtk_rekey_count %d "
3121 		    "igtk_rekey_count %d bss_index %d\n",
3122 		    rsp->status, rsp->last_rekey_status,
3123 		    rsp->key_replay_counter, rsp->total_rekey_count,
3124 		    rsp->gtk_rekey_count, rsp->igtk_rekey_count,
3125 		    rsp->bss_index);
3126 
3127 	return 0;
3128 }
3129 
3130 int wcn36xx_smd_gtk_offload_get_info(struct wcn36xx *wcn,
3131 				     struct ieee80211_vif *vif)
3132 {
3133 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3134 	struct wcn36xx_hal_gtk_offload_get_info_req_msg msg_body;
3135 	int ret;
3136 
3137 	mutex_lock(&wcn->hal_mutex);
3138 
3139 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_GTK_OFFLOAD_GETINFO_REQ);
3140 
3141 	msg_body.bss_index = vif_priv->bss_index;
3142 
3143 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3144 
3145 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3146 	if (ret) {
3147 		wcn36xx_err("Sending gtk_offload_get_info failed\n");
3148 		goto out;
3149 	}
3150 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3151 	if (ret) {
3152 		wcn36xx_err("gtk_offload_get_info failed err=%d\n", ret);
3153 		goto out;
3154 	}
3155 	ret = wcn36xx_smd_gtk_offload_get_info_rsp(wcn, vif);
3156 out:
3157 	mutex_unlock(&wcn->hal_mutex);
3158 	return ret;
3159 }
3160 
3161 int wcn36xx_smd_wlan_host_suspend_ind(struct wcn36xx *wcn)
3162 {
3163 	struct wcn36xx_hal_wlan_host_suspend_ind_msg msg_body;
3164 	int ret;
3165 
3166 	mutex_lock(&wcn->hal_mutex);
3167 
3168 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_SUSPEND_IND);
3169 	msg_body.configured_mcst_bcst_filter_setting = 0;
3170 	msg_body.active_session_count = 1;
3171 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3172 
3173 	ret = rpmsg_send(wcn->smd_channel, wcn->hal_buf, msg_body.header.len);
3174 
3175 	mutex_unlock(&wcn->hal_mutex);
3176 
3177 	return ret;
3178 }
3179 
3180 int wcn36xx_smd_host_resume(struct wcn36xx *wcn)
3181 {
3182 	struct wcn36xx_hal_wlan_host_resume_req_msg msg_body;
3183 	struct wcn36xx_hal_host_resume_rsp_msg *rsp;
3184 	int ret;
3185 
3186 	mutex_lock(&wcn->hal_mutex);
3187 
3188 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_RESUME_REQ);
3189 	msg_body.configured_mcst_bcst_filter_setting = 0;
3190 
3191 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3192 
3193 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3194 	if (ret) {
3195 		wcn36xx_err("Sending wlan_host_resume failed\n");
3196 		goto out;
3197 	}
3198 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3199 	if (ret) {
3200 		wcn36xx_err("wlan_host_resume err=%d\n", ret);
3201 		goto out;
3202 	}
3203 
3204 	rsp = (struct wcn36xx_hal_host_resume_rsp_msg *)wcn->hal_buf;
3205 	if (rsp->status)
3206 		wcn36xx_warn("wlan_host_resume status=%d\n", rsp->status);
3207 
3208 out:
3209 	mutex_unlock(&wcn->hal_mutex);
3210 
3211 	return ret;
3212 }
3213 
3214 #define BEACON_FILTER(eid, presence, offs, val, mask, ref_val) \
3215 	{					\
3216 		.element_id = eid,		\
3217 		.check_ie_presence = presence,	\
3218 		.offset = offs,			\
3219 		.value = val,			\
3220 		.bitmask = mask,		\
3221 		.ref = ref_val,			\
3222 	}
3223 
3224 static const struct beacon_filter_ie bcn_filter_ies[] = {
3225 	BEACON_FILTER(WLAN_EID_DS_PARAMS, 0, 0, 0,
3226 		      WCN36XX_FILTER_IE_DS_CHANNEL_MASK, 0),
3227 	BEACON_FILTER(WLAN_EID_ERP_INFO, 0, 0, 0,
3228 		      WCN36XX_FILTER_IE_ERP_FILTER_MASK, 0),
3229 	BEACON_FILTER(WLAN_EID_EDCA_PARAM_SET, 0, 0, 0,
3230 		      WCN36XX_FILTER_IE_EDCA_FILTER_MASK, 0),
3231 	BEACON_FILTER(WLAN_EID_QOS_CAPA, 0, 0, 0,
3232 		      WCN36XX_FILTER_IE_QOS_FILTER_MASK, 0),
3233 	BEACON_FILTER(WLAN_EID_CHANNEL_SWITCH, 1, 0, 0,
3234 		      WCN36XX_FILTER_IE_CHANNEL_SWITCH_MASK, 0),
3235 	BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 0, 0,
3236 		      WCN36XX_FILTER_IE_HT_BYTE0_FILTER_MASK, 0),
3237 	BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 2, 0,
3238 		      WCN36XX_FILTER_IE_HT_BYTE2_FILTER_MASK, 0),
3239 	BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 5, 0,
3240 		      WCN36XX_FILTER_IE_HT_BYTE5_FILTER_MASK, 0),
3241 	BEACON_FILTER(WLAN_EID_PWR_CONSTRAINT, 0, 0, 0,
3242 		      WCN36XX_FILTER_IE_PWR_CONSTRAINT_MASK, 0),
3243 	BEACON_FILTER(WLAN_EID_OPMODE_NOTIF, 0, 0, 0,
3244 		      WCN36XX_FILTER_IE_OPMODE_NOTIF_MASK, 0),
3245 	BEACON_FILTER(WLAN_EID_VHT_OPERATION, 0, 0, 0,
3246 		      WCN36XX_FILTER_IE_VHTOP_CHWIDTH_MASK, 0),
3247 	BEACON_FILTER(WLAN_EID_RSN, 1, 0, 0,
3248 		      WCN36XX_FILTER_IE_RSN_MASK, 0),
3249 	BEACON_FILTER(WLAN_EID_VENDOR_SPECIFIC, 1, 0, 0,
3250 		      WCN36XX_FILTER_IE_VENDOR_MASK, 0),
3251 };
3252 
3253 int wcn36xx_smd_add_beacon_filter(struct wcn36xx *wcn,
3254 				  struct ieee80211_vif *vif)
3255 {
3256 	struct wcn36xx_hal_add_bcn_filter_req_msg msg_body, *body;
3257 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3258 	u8 *payload;
3259 	size_t payload_size;
3260 	int ret;
3261 
3262 	if (!wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, BCN_FILTER))
3263 		return -EOPNOTSUPP;
3264 
3265 	mutex_lock(&wcn->hal_mutex);
3266 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BCN_FILTER_REQ);
3267 
3268 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3269 
3270 	body = (struct wcn36xx_hal_add_bcn_filter_req_msg *)wcn->hal_buf;
3271 	body->capability_info = vif->bss_conf.assoc_capability;
3272 	body->capability_mask = WCN36XX_FILTER_CAPABILITY_MASK;
3273 	body->beacon_interval = vif->bss_conf.beacon_int;
3274 	body->ie_num = ARRAY_SIZE(bcn_filter_ies);
3275 	body->bss_index = vif_priv->bss_index;
3276 
3277 	payload = ((u8 *)body) + body->header.len;
3278 	payload_size = sizeof(bcn_filter_ies);
3279 	memcpy(payload, &bcn_filter_ies, payload_size);
3280 
3281 	body->header.len += payload_size;
3282 
3283 	ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
3284 	if (ret) {
3285 		wcn36xx_err("Sending add bcn_filter failed\n");
3286 		goto out;
3287 	}
3288 
3289 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3290 	if (ret) {
3291 		wcn36xx_err("add bcn filter response failed err=%d\n", ret);
3292 		goto out;
3293 	}
3294 out:
3295 	mutex_unlock(&wcn->hal_mutex);
3296 	return ret;
3297 }
3298 
3299 int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
3300 			    void *buf, int len, void *priv, u32 addr)
3301 {
3302 	const struct wcn36xx_hal_msg_header *msg_header = buf;
3303 	struct ieee80211_hw *hw = priv;
3304 	struct wcn36xx *wcn = hw->priv;
3305 	struct wcn36xx_hal_ind_msg *msg_ind;
3306 	wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
3307 
3308 	switch (msg_header->msg_type) {
3309 	case WCN36XX_HAL_START_RSP:
3310 	case WCN36XX_HAL_CONFIG_STA_RSP:
3311 	case WCN36XX_HAL_CONFIG_BSS_RSP:
3312 	case WCN36XX_HAL_ADD_STA_SELF_RSP:
3313 	case WCN36XX_HAL_STOP_RSP:
3314 	case WCN36XX_HAL_DEL_STA_SELF_RSP:
3315 	case WCN36XX_HAL_DELETE_STA_RSP:
3316 	case WCN36XX_HAL_INIT_SCAN_RSP:
3317 	case WCN36XX_HAL_START_SCAN_RSP:
3318 	case WCN36XX_HAL_END_SCAN_RSP:
3319 	case WCN36XX_HAL_FINISH_SCAN_RSP:
3320 	case WCN36XX_HAL_DOWNLOAD_NV_RSP:
3321 	case WCN36XX_HAL_DELETE_BSS_RSP:
3322 	case WCN36XX_HAL_SEND_BEACON_RSP:
3323 	case WCN36XX_HAL_SET_LINK_ST_RSP:
3324 	case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP:
3325 	case WCN36XX_HAL_SET_BSSKEY_RSP:
3326 	case WCN36XX_HAL_SET_STAKEY_RSP:
3327 	case WCN36XX_HAL_RMV_STAKEY_RSP:
3328 	case WCN36XX_HAL_RMV_BSSKEY_RSP:
3329 	case WCN36XX_HAL_ENTER_BMPS_RSP:
3330 	case WCN36XX_HAL_SET_POWER_PARAMS_RSP:
3331 	case WCN36XX_HAL_EXIT_BMPS_RSP:
3332 	case WCN36XX_HAL_KEEP_ALIVE_RSP:
3333 	case WCN36XX_HAL_DUMP_COMMAND_RSP:
3334 	case WCN36XX_HAL_ADD_BA_SESSION_RSP:
3335 	case WCN36XX_HAL_ADD_BA_RSP:
3336 	case WCN36XX_HAL_DEL_BA_RSP:
3337 	case WCN36XX_HAL_GET_STATS_RSP:
3338 	case WCN36XX_HAL_TRIGGER_BA_RSP:
3339 	case WCN36XX_HAL_UPDATE_CFG_RSP:
3340 	case WCN36XX_HAL_JOIN_RSP:
3341 	case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP:
3342 	case WCN36XX_HAL_CH_SWITCH_RSP:
3343 	case WCN36XX_HAL_PROCESS_PTT_RSP:
3344 	case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
3345 	case WCN36XX_HAL_8023_MULTICAST_LIST_RSP:
3346 	case WCN36XX_HAL_START_SCAN_OFFLOAD_RSP:
3347 	case WCN36XX_HAL_STOP_SCAN_OFFLOAD_RSP:
3348 	case WCN36XX_HAL_HOST_OFFLOAD_RSP:
3349 	case WCN36XX_HAL_GTK_OFFLOAD_RSP:
3350 	case WCN36XX_HAL_GTK_OFFLOAD_GETINFO_RSP:
3351 	case WCN36XX_HAL_HOST_RESUME_RSP:
3352 	case WCN36XX_HAL_ENTER_IMPS_RSP:
3353 	case WCN36XX_HAL_EXIT_IMPS_RSP:
3354 	case WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP:
3355 	case WCN36XX_HAL_ADD_BCN_FILTER_RSP:
3356 		memcpy(wcn->hal_buf, buf, len);
3357 		wcn->hal_rsp_len = len;
3358 		complete(&wcn->hal_rsp_compl);
3359 		break;
3360 
3361 	case WCN36XX_HAL_COEX_IND:
3362 	case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
3363 	case WCN36XX_HAL_DEL_BA_IND:
3364 	case WCN36XX_HAL_OTA_TX_COMPL_IND:
3365 	case WCN36XX_HAL_MISSED_BEACON_IND:
3366 	case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
3367 	case WCN36XX_HAL_PRINT_REG_INFO_IND:
3368 	case WCN36XX_HAL_SCAN_OFFLOAD_IND:
3369 		msg_ind = kmalloc(struct_size(msg_ind, msg, len), GFP_ATOMIC);
3370 		if (!msg_ind) {
3371 			wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
3372 				    msg_header->msg_type);
3373 			return -ENOMEM;
3374 		}
3375 
3376 		msg_ind->msg_len = len;
3377 		memcpy(msg_ind->msg, buf, len);
3378 
3379 		spin_lock(&wcn->hal_ind_lock);
3380 		list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
3381 		queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
3382 		spin_unlock(&wcn->hal_ind_lock);
3383 		wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
3384 		break;
3385 	default:
3386 		wcn36xx_err("SMD_EVENT (%d) not supported\n",
3387 			      msg_header->msg_type);
3388 	}
3389 
3390 	return 0;
3391 }
3392 
3393 static void wcn36xx_ind_smd_work(struct work_struct *work)
3394 {
3395 	struct wcn36xx *wcn =
3396 		container_of(work, struct wcn36xx, hal_ind_work);
3397 
3398 	for (;;) {
3399 		struct wcn36xx_hal_msg_header *msg_header;
3400 		struct wcn36xx_hal_ind_msg *hal_ind_msg;
3401 		unsigned long flags;
3402 
3403 		spin_lock_irqsave(&wcn->hal_ind_lock, flags);
3404 
3405 		if (list_empty(&wcn->hal_ind_queue)) {
3406 			spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
3407 			return;
3408 		}
3409 
3410 		hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
3411 					       struct wcn36xx_hal_ind_msg,
3412 					       list);
3413 		list_del(&hal_ind_msg->list);
3414 		spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
3415 
3416 		msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
3417 
3418 		switch (msg_header->msg_type) {
3419 		case WCN36XX_HAL_COEX_IND:
3420 		case WCN36XX_HAL_DEL_BA_IND:
3421 		case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
3422 			break;
3423 		case WCN36XX_HAL_OTA_TX_COMPL_IND:
3424 			wcn36xx_smd_tx_compl_ind(wcn,
3425 						 hal_ind_msg->msg,
3426 						 hal_ind_msg->msg_len);
3427 			break;
3428 		case WCN36XX_HAL_MISSED_BEACON_IND:
3429 			wcn36xx_smd_missed_beacon_ind(wcn,
3430 						      hal_ind_msg->msg,
3431 						      hal_ind_msg->msg_len);
3432 			break;
3433 		case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
3434 			wcn36xx_smd_delete_sta_context_ind(wcn,
3435 							   hal_ind_msg->msg,
3436 							   hal_ind_msg->msg_len);
3437 			break;
3438 		case WCN36XX_HAL_PRINT_REG_INFO_IND:
3439 			wcn36xx_smd_print_reg_info_ind(wcn,
3440 						       hal_ind_msg->msg,
3441 						       hal_ind_msg->msg_len);
3442 			break;
3443 		case WCN36XX_HAL_SCAN_OFFLOAD_IND:
3444 			wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg,
3445 						hal_ind_msg->msg_len);
3446 			break;
3447 		default:
3448 			wcn36xx_err("SMD_EVENT (%d) not supported\n",
3449 				    msg_header->msg_type);
3450 		}
3451 
3452 		kfree(hal_ind_msg);
3453 	}
3454 }
3455 
3456 int wcn36xx_smd_open(struct wcn36xx *wcn)
3457 {
3458 	wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind");
3459 	if (!wcn->hal_ind_wq)
3460 		return -ENOMEM;
3461 
3462 	INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
3463 	INIT_LIST_HEAD(&wcn->hal_ind_queue);
3464 	spin_lock_init(&wcn->hal_ind_lock);
3465 
3466 	return 0;
3467 }
3468 
3469 void wcn36xx_smd_close(struct wcn36xx *wcn)
3470 {
3471 	struct wcn36xx_hal_ind_msg *msg, *tmp;
3472 
3473 	cancel_work_sync(&wcn->hal_ind_work);
3474 	destroy_workqueue(wcn->hal_ind_wq);
3475 
3476 	list_for_each_entry_safe(msg, tmp, &wcn->hal_ind_queue, list)
3477 		kfree(msg);
3478 }
3479