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