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