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, 6),
49 	WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 6),
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 };
81 
82 static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value)
83 {
84 	struct wcn36xx_hal_cfg *entry;
85 	u32 *val;
86 
87 	if (*len + sizeof(*entry) + sizeof(u32) >= WCN36XX_HAL_BUF_SIZE) {
88 		wcn36xx_err("Not enough room for TLV entry\n");
89 		return -ENOMEM;
90 	}
91 
92 	entry = (struct wcn36xx_hal_cfg *) (wcn->hal_buf + *len);
93 	entry->id = id;
94 	entry->len = sizeof(u32);
95 	entry->pad_bytes = 0;
96 	entry->reserve = 0;
97 
98 	val = (u32 *) (entry + 1);
99 	*val = value;
100 
101 	*len += sizeof(*entry) + sizeof(u32);
102 
103 	return 0;
104 }
105 
106 static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn,
107 		struct ieee80211_sta *sta,
108 		struct wcn36xx_hal_config_bss_params *bss_params)
109 {
110 	if (NL80211_BAND_5GHZ == WCN36XX_BAND(wcn))
111 		bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE;
112 	else if (sta && sta->ht_cap.ht_supported)
113 		bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE;
114 	else if (sta && (sta->supp_rates[NL80211_BAND_2GHZ] & 0x7f))
115 		bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE;
116 	else
117 		bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE;
118 }
119 
120 static inline u8 is_cap_supported(unsigned long caps, unsigned long flag)
121 {
122 	return caps & flag ? 1 : 0;
123 }
124 static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif,
125 		struct ieee80211_sta *sta,
126 		struct wcn36xx_hal_config_bss_params *bss_params)
127 {
128 	if (sta && sta->ht_cap.ht_supported) {
129 		unsigned long caps = sta->ht_cap.cap;
130 		bss_params->ht = sta->ht_cap.ht_supported;
131 		bss_params->tx_channel_width_set = is_cap_supported(caps,
132 			IEEE80211_HT_CAP_SUP_WIDTH_20_40);
133 		bss_params->lsig_tx_op_protection_full_support =
134 			is_cap_supported(caps,
135 					 IEEE80211_HT_CAP_LSIG_TXOP_PROT);
136 
137 		bss_params->ht_oper_mode = vif->bss_conf.ht_operation_mode;
138 		bss_params->lln_non_gf_coexist =
139 			!!(vif->bss_conf.ht_operation_mode &
140 			   IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
141 		/* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */
142 		bss_params->dual_cts_protection = 0;
143 		/* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */
144 		bss_params->ht20_coexist = 0;
145 	}
146 }
147 
148 static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta,
149 		struct wcn36xx_hal_config_sta_params *sta_params)
150 {
151 	if (sta->ht_cap.ht_supported) {
152 		unsigned long caps = sta->ht_cap.cap;
153 		sta_params->ht_capable = sta->ht_cap.ht_supported;
154 		sta_params->tx_channel_width_set = is_cap_supported(caps,
155 			IEEE80211_HT_CAP_SUP_WIDTH_20_40);
156 		sta_params->lsig_txop_protection = is_cap_supported(caps,
157 			IEEE80211_HT_CAP_LSIG_TXOP_PROT);
158 
159 		sta_params->max_ampdu_size = sta->ht_cap.ampdu_factor;
160 		sta_params->max_ampdu_density = sta->ht_cap.ampdu_density;
161 		sta_params->max_amsdu_size = is_cap_supported(caps,
162 			IEEE80211_HT_CAP_MAX_AMSDU);
163 		sta_params->sgi_20Mhz = is_cap_supported(caps,
164 			IEEE80211_HT_CAP_SGI_20);
165 		sta_params->sgi_40mhz =	is_cap_supported(caps,
166 			IEEE80211_HT_CAP_SGI_40);
167 		sta_params->green_field_capable = is_cap_supported(caps,
168 			IEEE80211_HT_CAP_GRN_FLD);
169 		sta_params->delayed_ba_support = is_cap_supported(caps,
170 			IEEE80211_HT_CAP_DELAY_BA);
171 		sta_params->dsss_cck_mode_40mhz = is_cap_supported(caps,
172 			IEEE80211_HT_CAP_DSSSCCK40);
173 	}
174 }
175 
176 static void wcn36xx_smd_set_sta_default_ht_params(
177 		struct wcn36xx_hal_config_sta_params *sta_params)
178 {
179 	sta_params->ht_capable = 1;
180 	sta_params->tx_channel_width_set = 1;
181 	sta_params->lsig_txop_protection = 1;
182 	sta_params->max_ampdu_size = 3;
183 	sta_params->max_ampdu_density = 5;
184 	sta_params->max_amsdu_size = 0;
185 	sta_params->sgi_20Mhz = 1;
186 	sta_params->sgi_40mhz = 1;
187 	sta_params->green_field_capable = 1;
188 	sta_params->delayed_ba_support = 0;
189 	sta_params->dsss_cck_mode_40mhz = 1;
190 }
191 
192 static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
193 		struct ieee80211_vif *vif,
194 		struct ieee80211_sta *sta,
195 		struct wcn36xx_hal_config_sta_params *sta_params)
196 {
197 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
198 	struct wcn36xx_sta *sta_priv = NULL;
199 	if (vif->type == NL80211_IFTYPE_ADHOC ||
200 	    vif->type == NL80211_IFTYPE_AP ||
201 	    vif->type == NL80211_IFTYPE_MESH_POINT) {
202 		sta_params->type = 1;
203 		sta_params->sta_index = WCN36XX_HAL_STA_INVALID_IDX;
204 	} else {
205 		sta_params->type = 0;
206 		sta_params->sta_index = vif_priv->self_sta_index;
207 	}
208 
209 	sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
210 
211 	/*
212 	 * In STA mode ieee80211_sta contains bssid and ieee80211_vif
213 	 * contains our mac address. In  AP mode we are bssid so vif
214 	 * contains bssid and ieee80211_sta contains mac.
215 	 */
216 	if (NL80211_IFTYPE_STATION == vif->type)
217 		memcpy(&sta_params->mac, vif->addr, ETH_ALEN);
218 	else
219 		memcpy(&sta_params->bssid, vif->addr, ETH_ALEN);
220 
221 	sta_params->encrypt_type = vif_priv->encrypt_type;
222 	sta_params->short_preamble_supported = true;
223 
224 	sta_params->rifs_mode = 0;
225 	sta_params->rmf = 0;
226 	sta_params->action = 0;
227 	sta_params->uapsd = 0;
228 	sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC;
229 	sta_params->max_ampdu_duration = 0;
230 	sta_params->bssid_index = vif_priv->bss_index;
231 	sta_params->p2p = 0;
232 
233 	if (sta) {
234 		sta_priv = wcn36xx_sta_to_priv(sta);
235 		if (NL80211_IFTYPE_STATION == vif->type)
236 			memcpy(&sta_params->bssid, sta->addr, ETH_ALEN);
237 		else
238 			memcpy(&sta_params->mac, sta->addr, ETH_ALEN);
239 		sta_params->wmm_enabled = sta->wme;
240 		sta_params->max_sp_len = sta->max_sp;
241 		sta_params->aid = sta_priv->aid;
242 		wcn36xx_smd_set_sta_ht_params(sta, sta_params);
243 		memcpy(&sta_params->supported_rates, &sta_priv->supported_rates,
244 			sizeof(sta_priv->supported_rates));
245 	} else {
246 		wcn36xx_set_default_rates(&sta_params->supported_rates);
247 		wcn36xx_smd_set_sta_default_ht_params(sta_params);
248 	}
249 }
250 
251 static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
252 {
253 	int ret = 0;
254 	unsigned long start;
255 	struct wcn36xx_hal_msg_header *hdr =
256 		(struct wcn36xx_hal_msg_header *)wcn->hal_buf;
257 	u16 req_type = hdr->msg_type;
258 
259 	wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len);
260 
261 	init_completion(&wcn->hal_rsp_compl);
262 	start = jiffies;
263 	ret = rpmsg_send(wcn->smd_channel, wcn->hal_buf, len);
264 	if (ret) {
265 		wcn36xx_err("HAL TX failed for req %d\n", req_type);
266 		goto out;
267 	}
268 	if (wait_for_completion_timeout(&wcn->hal_rsp_compl,
269 		msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) {
270 		wcn36xx_err("Timeout! No SMD response to req %d in %dms\n",
271 			    req_type, HAL_MSG_TIMEOUT);
272 		ret = -ETIME;
273 		goto out;
274 	}
275 	wcn36xx_dbg(WCN36XX_DBG_SMD,
276 		    "SMD command (req %d, rsp %d) completed in %dms\n",
277 		    req_type, hdr->msg_type,
278 		    jiffies_to_msecs(jiffies - start));
279 out:
280 	return ret;
281 }
282 
283 static void init_hal_msg(struct wcn36xx_hal_msg_header *hdr,
284 			 enum wcn36xx_hal_host_msg_type msg_type,
285 			 size_t msg_size)
286 {
287 	memset(hdr, 0, msg_size + sizeof(*hdr));
288 	hdr->msg_type = msg_type;
289 	hdr->msg_version = WCN36XX_HAL_MSG_VERSION0;
290 	hdr->len = msg_size + sizeof(*hdr);
291 }
292 
293 #define INIT_HAL_MSG(msg_body, type) \
294 	do {								\
295 		memset(&msg_body, 0, sizeof(msg_body));			\
296 		msg_body.header.msg_type = type;			\
297 		msg_body.header.msg_version = WCN36XX_HAL_MSG_VERSION0; \
298 		msg_body.header.len = sizeof(msg_body);			\
299 	} while (0)							\
300 
301 #define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \
302 	do { \
303 		memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \
304 		p_msg_body->header.msg_type = WCN36XX_HAL_PROCESS_PTT_REQ; \
305 		p_msg_body->header.msg_version = WCN36XX_HAL_MSG_VERSION0; \
306 		p_msg_body->header.len = sizeof(*p_msg_body) + ppt_msg_len; \
307 	} while (0)
308 
309 #define PREPARE_HAL_BUF(send_buf, msg_body) \
310 	do {							\
311 		memset(send_buf, 0, msg_body.header.len);	\
312 		memcpy(send_buf, &msg_body, sizeof(msg_body));	\
313 	} while (0)						\
314 
315 #define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \
316 	do {							\
317 		memset(send_buf, 0, p_msg_body->header.len); \
318 		memcpy(send_buf, p_msg_body, p_msg_body->header.len); \
319 	} while (0)
320 
321 static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
322 {
323 	struct wcn36xx_fw_msg_status_rsp *rsp;
324 
325 	if (len < sizeof(struct wcn36xx_hal_msg_header) +
326 	    sizeof(struct wcn36xx_fw_msg_status_rsp))
327 		return -EIO;
328 
329 	rsp = (struct wcn36xx_fw_msg_status_rsp *)
330 		(buf + sizeof(struct wcn36xx_hal_msg_header));
331 
332 	if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
333 		return rsp->status;
334 
335 	return 0;
336 }
337 
338 int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
339 {
340 	struct nv_data *nv_d;
341 	struct wcn36xx_hal_nv_img_download_req_msg msg_body;
342 	int fw_bytes_left;
343 	int ret;
344 	u16 fm_offset = 0;
345 
346 	if (!wcn->nv) {
347 		ret = request_firmware(&wcn->nv, WLAN_NV_FILE, wcn->dev);
348 		if (ret) {
349 			wcn36xx_err("Failed to load nv file %s: %d\n",
350 				      WLAN_NV_FILE, ret);
351 			goto out;
352 		}
353 	}
354 
355 	nv_d = (struct nv_data *)wcn->nv->data;
356 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ);
357 
358 	msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE;
359 
360 	msg_body.frag_number = 0;
361 	/* hal_buf must be protected with  mutex */
362 	mutex_lock(&wcn->hal_mutex);
363 
364 	do {
365 		fw_bytes_left = wcn->nv->size - fm_offset - 4;
366 		if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) {
367 			msg_body.last_fragment = 0;
368 			msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE;
369 		} else {
370 			msg_body.last_fragment = 1;
371 			msg_body.nv_img_buffer_size = fw_bytes_left;
372 
373 			/* Do not forget update general message len */
374 			msg_body.header.len = sizeof(msg_body) + fw_bytes_left;
375 
376 		}
377 
378 		/* Add load NV request message header */
379 		memcpy(wcn->hal_buf, &msg_body,	sizeof(msg_body));
380 
381 		/* Add NV body itself */
382 		memcpy(wcn->hal_buf + sizeof(msg_body),
383 		       &nv_d->table + fm_offset,
384 		       msg_body.nv_img_buffer_size);
385 
386 		ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
387 		if (ret)
388 			goto out_unlock;
389 		ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf,
390 						   wcn->hal_rsp_len);
391 		if (ret) {
392 			wcn36xx_err("hal_load_nv response failed err=%d\n",
393 				    ret);
394 			goto out_unlock;
395 		}
396 		msg_body.frag_number++;
397 		fm_offset += WCN36XX_NV_FRAGMENT_SIZE;
398 
399 	} while (msg_body.last_fragment != 1);
400 
401 out_unlock:
402 	mutex_unlock(&wcn->hal_mutex);
403 out:	return ret;
404 }
405 
406 static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
407 {
408 	struct wcn36xx_hal_mac_start_rsp_msg *rsp;
409 
410 	if (len < sizeof(*rsp))
411 		return -EIO;
412 
413 	rsp = (struct wcn36xx_hal_mac_start_rsp_msg *)buf;
414 
415 	if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->start_rsp_params.status)
416 		return -EIO;
417 
418 	memcpy(wcn->crm_version, rsp->start_rsp_params.crm_version,
419 	       WCN36XX_HAL_VERSION_LENGTH);
420 	memcpy(wcn->wlan_version, rsp->start_rsp_params.wlan_version,
421 	       WCN36XX_HAL_VERSION_LENGTH);
422 
423 	/* null terminate the strings, just in case */
424 	wcn->crm_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
425 	wcn->wlan_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
426 
427 	wcn->fw_revision = rsp->start_rsp_params.version.revision;
428 	wcn->fw_version = rsp->start_rsp_params.version.version;
429 	wcn->fw_minor = rsp->start_rsp_params.version.minor;
430 	wcn->fw_major = rsp->start_rsp_params.version.major;
431 
432 	if (wcn->first_boot) {
433 		wcn->first_boot = false;
434 		wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n",
435 			     wcn->wlan_version, wcn->crm_version);
436 
437 		wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n",
438 			     wcn->fw_major, wcn->fw_minor,
439 			     wcn->fw_version, wcn->fw_revision,
440 			     rsp->start_rsp_params.stations,
441 			     rsp->start_rsp_params.bssids);
442 	}
443 	return 0;
444 }
445 
446 int wcn36xx_smd_start(struct wcn36xx *wcn)
447 {
448 	struct wcn36xx_hal_mac_start_req_msg msg_body, *body;
449 	int ret = 0;
450 	int i;
451 	size_t len;
452 
453 	mutex_lock(&wcn->hal_mutex);
454 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ);
455 
456 	msg_body.params.type = DRIVER_TYPE_PRODUCTION;
457 	msg_body.params.len = 0;
458 
459 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
460 
461 	body = (struct wcn36xx_hal_mac_start_req_msg *)wcn->hal_buf;
462 	len = body->header.len;
463 
464 	for (i = 0; i < ARRAY_SIZE(wcn36xx_cfg_vals); i++) {
465 		ret = put_cfg_tlv_u32(wcn, &len, wcn36xx_cfg_vals[i].cfg_id,
466 				      wcn36xx_cfg_vals[i].value);
467 		if (ret)
468 			goto out;
469 	}
470 	body->header.len = len;
471 	body->params.len = len - sizeof(*body);
472 
473 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n",
474 		    msg_body.params.type);
475 
476 	ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
477 	if (ret) {
478 		wcn36xx_err("Sending hal_start failed\n");
479 		goto out;
480 	}
481 
482 	ret = wcn36xx_smd_start_rsp(wcn, wcn->hal_buf, wcn->hal_rsp_len);
483 	if (ret) {
484 		wcn36xx_err("hal_start response failed err=%d\n", ret);
485 		goto out;
486 	}
487 
488 out:
489 	mutex_unlock(&wcn->hal_mutex);
490 	return ret;
491 }
492 
493 int wcn36xx_smd_stop(struct wcn36xx *wcn)
494 {
495 	struct wcn36xx_hal_mac_stop_req_msg msg_body;
496 	int ret = 0;
497 
498 	mutex_lock(&wcn->hal_mutex);
499 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ);
500 
501 	msg_body.stop_req_params.reason = HAL_STOP_TYPE_RF_KILL;
502 
503 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
504 
505 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
506 	if (ret) {
507 		wcn36xx_err("Sending hal_stop failed\n");
508 		goto out;
509 	}
510 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
511 	if (ret) {
512 		wcn36xx_err("hal_stop response failed err=%d\n", ret);
513 		goto out;
514 	}
515 out:
516 	mutex_unlock(&wcn->hal_mutex);
517 	return ret;
518 }
519 
520 int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode)
521 {
522 	struct wcn36xx_hal_init_scan_req_msg msg_body;
523 	int ret = 0;
524 
525 	mutex_lock(&wcn->hal_mutex);
526 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ);
527 
528 	msg_body.mode = mode;
529 
530 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
531 
532 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d\n", msg_body.mode);
533 
534 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
535 	if (ret) {
536 		wcn36xx_err("Sending hal_init_scan failed\n");
537 		goto out;
538 	}
539 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
540 	if (ret) {
541 		wcn36xx_err("hal_init_scan response failed err=%d\n", ret);
542 		goto out;
543 	}
544 out:
545 	mutex_unlock(&wcn->hal_mutex);
546 	return ret;
547 }
548 
549 int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel)
550 {
551 	struct wcn36xx_hal_start_scan_req_msg msg_body;
552 	int ret = 0;
553 
554 	mutex_lock(&wcn->hal_mutex);
555 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ);
556 
557 	msg_body.scan_channel = scan_channel;
558 
559 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
560 
561 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start scan channel %d\n",
562 		    msg_body.scan_channel);
563 
564 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
565 	if (ret) {
566 		wcn36xx_err("Sending hal_start_scan failed\n");
567 		goto out;
568 	}
569 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
570 	if (ret) {
571 		wcn36xx_err("hal_start_scan response failed err=%d\n", ret);
572 		goto out;
573 	}
574 out:
575 	mutex_unlock(&wcn->hal_mutex);
576 	return ret;
577 }
578 
579 int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel)
580 {
581 	struct wcn36xx_hal_end_scan_req_msg msg_body;
582 	int ret = 0;
583 
584 	mutex_lock(&wcn->hal_mutex);
585 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ);
586 
587 	msg_body.scan_channel = scan_channel;
588 
589 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
590 
591 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d\n",
592 		    msg_body.scan_channel);
593 
594 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
595 	if (ret) {
596 		wcn36xx_err("Sending hal_end_scan failed\n");
597 		goto out;
598 	}
599 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
600 	if (ret) {
601 		wcn36xx_err("hal_end_scan response failed err=%d\n", ret);
602 		goto out;
603 	}
604 out:
605 	mutex_unlock(&wcn->hal_mutex);
606 	return ret;
607 }
608 
609 int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
610 			    enum wcn36xx_hal_sys_mode mode)
611 {
612 	struct wcn36xx_hal_finish_scan_req_msg msg_body;
613 	int ret = 0;
614 
615 	mutex_lock(&wcn->hal_mutex);
616 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ);
617 
618 	msg_body.mode = mode;
619 
620 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
621 
622 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal finish scan mode %d\n",
623 		    msg_body.mode);
624 
625 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
626 	if (ret) {
627 		wcn36xx_err("Sending hal_finish_scan failed\n");
628 		goto out;
629 	}
630 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
631 	if (ret) {
632 		wcn36xx_err("hal_finish_scan response failed err=%d\n", ret);
633 		goto out;
634 	}
635 out:
636 	mutex_unlock(&wcn->hal_mutex);
637 	return ret;
638 }
639 
640 int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif,
641 			      struct cfg80211_scan_request *req)
642 {
643 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
644 	struct wcn36xx_hal_start_scan_offload_req_msg msg_body;
645 	int ret, i;
646 
647 	if (req->ie_len > WCN36XX_MAX_SCAN_IE_LEN)
648 		return -EINVAL;
649 
650 	mutex_lock(&wcn->hal_mutex);
651 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_OFFLOAD_REQ);
652 
653 	msg_body.scan_type = WCN36XX_HAL_SCAN_TYPE_ACTIVE;
654 	msg_body.min_ch_time = 30;
655 	msg_body.max_ch_time = 100;
656 	msg_body.scan_hidden = 1;
657 	memcpy(msg_body.mac, vif->addr, ETH_ALEN);
658 	msg_body.bss_type = vif_priv->bss_type;
659 	msg_body.p2p_search = vif->p2p;
660 
661 	msg_body.num_ssid = min_t(u8, req->n_ssids, ARRAY_SIZE(msg_body.ssids));
662 	for (i = 0; i < msg_body.num_ssid; i++) {
663 		msg_body.ssids[i].length = min_t(u8, req->ssids[i].ssid_len,
664 						sizeof(msg_body.ssids[i].ssid));
665 		memcpy(msg_body.ssids[i].ssid, req->ssids[i].ssid,
666 		       msg_body.ssids[i].length);
667 	}
668 
669 	msg_body.num_channel = min_t(u8, req->n_channels,
670 				     sizeof(msg_body.channels));
671 	for (i = 0; i < msg_body.num_channel; i++)
672 		msg_body.channels[i] = req->channels[i]->hw_value;
673 
674 	msg_body.header.len -= WCN36XX_MAX_SCAN_IE_LEN;
675 
676 	if (req->ie_len > 0) {
677 		msg_body.ie_len = req->ie_len;
678 		msg_body.header.len += req->ie_len;
679 		memcpy(msg_body.ie, req->ie, req->ie_len);
680 	}
681 
682 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
683 
684 	wcn36xx_dbg(WCN36XX_DBG_HAL,
685 		    "hal start hw-scan (channels: %u; ssids: %u; p2p: %s)\n",
686 		    msg_body.num_channel, msg_body.num_ssid,
687 		    msg_body.p2p_search ? "yes" : "no");
688 
689 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
690 	if (ret) {
691 		wcn36xx_err("Sending hal_start_scan_offload failed\n");
692 		goto out;
693 	}
694 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
695 	if (ret) {
696 		wcn36xx_err("hal_start_scan_offload response failed err=%d\n",
697 			    ret);
698 		goto out;
699 	}
700 out:
701 	mutex_unlock(&wcn->hal_mutex);
702 	return ret;
703 }
704 
705 int wcn36xx_smd_stop_hw_scan(struct wcn36xx *wcn)
706 {
707 	struct wcn36xx_hal_stop_scan_offload_req_msg msg_body;
708 	int ret;
709 
710 	mutex_lock(&wcn->hal_mutex);
711 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_SCAN_OFFLOAD_REQ);
712 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
713 
714 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal stop hw-scan\n");
715 
716 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
717 	if (ret) {
718 		wcn36xx_err("Sending hal_stop_scan_offload failed\n");
719 		goto out;
720 	}
721 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
722 	if (ret) {
723 		wcn36xx_err("hal_stop_scan_offload response failed err=%d\n",
724 			    ret);
725 		goto out;
726 	}
727 out:
728 	mutex_unlock(&wcn->hal_mutex);
729 	return ret;
730 }
731 
732 static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len)
733 {
734 	struct wcn36xx_hal_switch_channel_rsp_msg *rsp;
735 	int ret = 0;
736 
737 	ret = wcn36xx_smd_rsp_status_check(buf, len);
738 	if (ret)
739 		return ret;
740 	rsp = (struct wcn36xx_hal_switch_channel_rsp_msg *)buf;
741 	wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d\n",
742 		    rsp->channel_number, rsp->status);
743 	return ret;
744 }
745 
746 int wcn36xx_smd_switch_channel(struct wcn36xx *wcn,
747 			       struct ieee80211_vif *vif, int ch)
748 {
749 	struct wcn36xx_hal_switch_channel_req_msg msg_body;
750 	int ret = 0;
751 
752 	mutex_lock(&wcn->hal_mutex);
753 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ);
754 
755 	msg_body.channel_number = (u8)ch;
756 	msg_body.tx_mgmt_power = 0xbf;
757 	msg_body.max_tx_power = 0xbf;
758 	memcpy(msg_body.self_sta_mac_addr, vif->addr, ETH_ALEN);
759 
760 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
761 
762 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
763 	if (ret) {
764 		wcn36xx_err("Sending hal_switch_channel failed\n");
765 		goto out;
766 	}
767 	ret = wcn36xx_smd_switch_channel_rsp(wcn->hal_buf, wcn->hal_rsp_len);
768 	if (ret) {
769 		wcn36xx_err("hal_switch_channel response failed err=%d\n", ret);
770 		goto out;
771 	}
772 out:
773 	mutex_unlock(&wcn->hal_mutex);
774 	return ret;
775 }
776 
777 static int wcn36xx_smd_process_ptt_msg_rsp(void *buf, size_t len,
778 					   void **p_ptt_rsp_msg)
779 {
780 	struct wcn36xx_hal_process_ptt_msg_rsp_msg *rsp;
781 	int ret;
782 
783 	ret = wcn36xx_smd_rsp_status_check(buf, len);
784 	if (ret)
785 		return ret;
786 
787 	rsp = (struct wcn36xx_hal_process_ptt_msg_rsp_msg *)buf;
788 
789 	wcn36xx_dbg(WCN36XX_DBG_HAL, "process ptt msg responded with length %d\n",
790 		    rsp->header.len);
791 	wcn36xx_dbg_dump(WCN36XX_DBG_HAL_DUMP, "HAL_PTT_MSG_RSP:", rsp->ptt_msg,
792 			 rsp->header.len - sizeof(rsp->ptt_msg_resp_status));
793 
794 	if (rsp->header.len > 0) {
795 		*p_ptt_rsp_msg = kmalloc(rsp->header.len, GFP_ATOMIC);
796 		if (!*p_ptt_rsp_msg)
797 			return -ENOMEM;
798 		memcpy(*p_ptt_rsp_msg, rsp->ptt_msg, rsp->header.len);
799 	}
800 	return ret;
801 }
802 
803 int wcn36xx_smd_process_ptt_msg(struct wcn36xx *wcn,
804 				struct ieee80211_vif *vif, void *ptt_msg, size_t len,
805 		void **ptt_rsp_msg)
806 {
807 	struct wcn36xx_hal_process_ptt_msg_req_msg *p_msg_body;
808 	int ret;
809 
810 	mutex_lock(&wcn->hal_mutex);
811 	p_msg_body = kmalloc(
812 		sizeof(struct wcn36xx_hal_process_ptt_msg_req_msg) + len,
813 		GFP_ATOMIC);
814 	if (!p_msg_body) {
815 		ret = -ENOMEM;
816 		goto out_nomem;
817 	}
818 	INIT_HAL_PTT_MSG(p_msg_body, len);
819 
820 	memcpy(&p_msg_body->ptt_msg, ptt_msg, len);
821 
822 	PREPARE_HAL_PTT_MSG_BUF(wcn->hal_buf, p_msg_body);
823 
824 	ret = wcn36xx_smd_send_and_wait(wcn, p_msg_body->header.len);
825 	if (ret) {
826 		wcn36xx_err("Sending hal_process_ptt_msg failed\n");
827 		goto out;
828 	}
829 	ret = wcn36xx_smd_process_ptt_msg_rsp(wcn->hal_buf, wcn->hal_rsp_len,
830 					      ptt_rsp_msg);
831 	if (ret) {
832 		wcn36xx_err("process_ptt_msg response failed err=%d\n", ret);
833 		goto out;
834 	}
835 out:
836 	kfree(p_msg_body);
837 out_nomem:
838 	mutex_unlock(&wcn->hal_mutex);
839 	return ret;
840 }
841 
842 static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len)
843 {
844 	struct wcn36xx_hal_update_scan_params_resp *rsp;
845 
846 	rsp = (struct wcn36xx_hal_update_scan_params_resp *)buf;
847 
848 	/* Remove the PNO version bit */
849 	rsp->status &= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK));
850 
851 	if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) {
852 		wcn36xx_warn("error response from update scan\n");
853 		return rsp->status;
854 	}
855 
856 	return 0;
857 }
858 
859 int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn,
860 				   u8 *channels, size_t channel_count)
861 {
862 	struct wcn36xx_hal_update_scan_params_req_ex msg_body;
863 	int ret = 0;
864 
865 	mutex_lock(&wcn->hal_mutex);
866 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ);
867 
868 	msg_body.dot11d_enabled	= false;
869 	msg_body.dot11d_resolved = true;
870 
871 	msg_body.channel_count = channel_count;
872 	memcpy(msg_body.channels, channels, channel_count);
873 	msg_body.active_min_ch_time = 60;
874 	msg_body.active_max_ch_time = 120;
875 	msg_body.passive_min_ch_time = 60;
876 	msg_body.passive_max_ch_time = 110;
877 	msg_body.state = PHY_SINGLE_CHANNEL_CENTERED;
878 
879 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
880 
881 	wcn36xx_dbg(WCN36XX_DBG_HAL,
882 		    "hal update scan params channel_count %d\n",
883 		    msg_body.channel_count);
884 
885 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
886 	if (ret) {
887 		wcn36xx_err("Sending hal_update_scan_params failed\n");
888 		goto out;
889 	}
890 	ret = wcn36xx_smd_update_scan_params_rsp(wcn->hal_buf,
891 						 wcn->hal_rsp_len);
892 	if (ret) {
893 		wcn36xx_err("hal_update_scan_params response failed err=%d\n",
894 			    ret);
895 		goto out;
896 	}
897 out:
898 	mutex_unlock(&wcn->hal_mutex);
899 	return ret;
900 }
901 
902 static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
903 					struct ieee80211_vif *vif,
904 					void *buf,
905 					size_t len)
906 {
907 	struct wcn36xx_hal_add_sta_self_rsp_msg *rsp;
908 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
909 
910 	if (len < sizeof(*rsp))
911 		return -EINVAL;
912 
913 	rsp = (struct wcn36xx_hal_add_sta_self_rsp_msg *)buf;
914 
915 	if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
916 		wcn36xx_warn("hal add sta self failure: %d\n",
917 			     rsp->status);
918 		return rsp->status;
919 	}
920 
921 	wcn36xx_dbg(WCN36XX_DBG_HAL,
922 		    "hal add sta self status %d self_sta_index %d dpu_index %d\n",
923 		    rsp->status, rsp->self_sta_index, rsp->dpu_index);
924 
925 	vif_priv->self_sta_index = rsp->self_sta_index;
926 	vif_priv->self_dpu_desc_index = rsp->dpu_index;
927 
928 	return 0;
929 }
930 
931 int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif)
932 {
933 	struct wcn36xx_hal_add_sta_self_req msg_body;
934 	int ret = 0;
935 
936 	mutex_lock(&wcn->hal_mutex);
937 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ);
938 
939 	memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN);
940 
941 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
942 
943 	wcn36xx_dbg(WCN36XX_DBG_HAL,
944 		    "hal add sta self self_addr %pM status %d\n",
945 		    msg_body.self_addr, msg_body.status);
946 
947 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
948 	if (ret) {
949 		wcn36xx_err("Sending hal_add_sta_self failed\n");
950 		goto out;
951 	}
952 	ret = wcn36xx_smd_add_sta_self_rsp(wcn,
953 					   vif,
954 					   wcn->hal_buf,
955 					   wcn->hal_rsp_len);
956 	if (ret) {
957 		wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret);
958 		goto out;
959 	}
960 out:
961 	mutex_unlock(&wcn->hal_mutex);
962 	return ret;
963 }
964 
965 int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr)
966 {
967 	struct wcn36xx_hal_del_sta_self_req_msg msg_body;
968 	int ret = 0;
969 
970 	mutex_lock(&wcn->hal_mutex);
971 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ);
972 
973 	memcpy(&msg_body.self_addr, addr, ETH_ALEN);
974 
975 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
976 
977 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
978 	if (ret) {
979 		wcn36xx_err("Sending hal_delete_sta_self failed\n");
980 		goto out;
981 	}
982 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
983 	if (ret) {
984 		wcn36xx_err("hal_delete_sta_self response failed err=%d\n",
985 			    ret);
986 		goto out;
987 	}
988 out:
989 	mutex_unlock(&wcn->hal_mutex);
990 	return ret;
991 }
992 
993 int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index)
994 {
995 	struct wcn36xx_hal_delete_sta_req_msg msg_body;
996 	int ret = 0;
997 
998 	mutex_lock(&wcn->hal_mutex);
999 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ);
1000 
1001 	msg_body.sta_index = sta_index;
1002 
1003 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1004 
1005 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1006 		    "hal delete sta sta_index %d\n",
1007 		    msg_body.sta_index);
1008 
1009 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1010 	if (ret) {
1011 		wcn36xx_err("Sending hal_delete_sta failed\n");
1012 		goto out;
1013 	}
1014 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1015 	if (ret) {
1016 		wcn36xx_err("hal_delete_sta response failed err=%d\n", ret);
1017 		goto out;
1018 	}
1019 out:
1020 	mutex_unlock(&wcn->hal_mutex);
1021 	return ret;
1022 }
1023 
1024 static int wcn36xx_smd_join_rsp(void *buf, size_t len)
1025 {
1026 	struct wcn36xx_hal_join_rsp_msg *rsp;
1027 
1028 	if (wcn36xx_smd_rsp_status_check(buf, len))
1029 		return -EIO;
1030 
1031 	rsp = (struct wcn36xx_hal_join_rsp_msg *)buf;
1032 
1033 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1034 		    "hal rsp join status %d tx_mgmt_power %d\n",
1035 		    rsp->status, rsp->tx_mgmt_power);
1036 
1037 	return 0;
1038 }
1039 
1040 int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch)
1041 {
1042 	struct wcn36xx_hal_join_req_msg msg_body;
1043 	int ret = 0;
1044 
1045 	mutex_lock(&wcn->hal_mutex);
1046 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ);
1047 
1048 	memcpy(&msg_body.bssid, bssid, ETH_ALEN);
1049 	memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN);
1050 	msg_body.channel = ch;
1051 
1052 	if (conf_is_ht40_minus(&wcn->hw->conf))
1053 		msg_body.secondary_channel_offset =
1054 			PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
1055 	else if (conf_is_ht40_plus(&wcn->hw->conf))
1056 		msg_body.secondary_channel_offset =
1057 			PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
1058 	else
1059 		msg_body.secondary_channel_offset =
1060 			PHY_SINGLE_CHANNEL_CENTERED;
1061 
1062 	msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE;
1063 
1064 	msg_body.max_tx_power = 0xbf;
1065 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1066 
1067 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1068 		    "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n",
1069 		    msg_body.bssid, msg_body.self_sta_mac_addr,
1070 		    msg_body.channel, msg_body.link_state);
1071 
1072 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1073 	if (ret) {
1074 		wcn36xx_err("Sending hal_join failed\n");
1075 		goto out;
1076 	}
1077 	ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len);
1078 	if (ret) {
1079 		wcn36xx_err("hal_join response failed err=%d\n", ret);
1080 		goto out;
1081 	}
1082 out:
1083 	mutex_unlock(&wcn->hal_mutex);
1084 	return ret;
1085 }
1086 
1087 int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid,
1088 			    const u8 *sta_mac,
1089 			    enum wcn36xx_hal_link_state state)
1090 {
1091 	struct wcn36xx_hal_set_link_state_req_msg msg_body;
1092 	int ret = 0;
1093 
1094 	mutex_lock(&wcn->hal_mutex);
1095 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ);
1096 
1097 	memcpy(&msg_body.bssid, bssid, ETH_ALEN);
1098 	memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN);
1099 	msg_body.state = state;
1100 
1101 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1102 
1103 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1104 		    "hal set link state bssid %pM self_mac_addr %pM state %d\n",
1105 		    msg_body.bssid, msg_body.self_mac_addr, msg_body.state);
1106 
1107 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1108 	if (ret) {
1109 		wcn36xx_err("Sending hal_set_link_st failed\n");
1110 		goto out;
1111 	}
1112 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1113 	if (ret) {
1114 		wcn36xx_err("hal_set_link_st response failed err=%d\n", ret);
1115 		goto out;
1116 	}
1117 out:
1118 	mutex_unlock(&wcn->hal_mutex);
1119 	return ret;
1120 }
1121 
1122 static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn,
1123 			const struct wcn36xx_hal_config_sta_params *orig,
1124 			struct wcn36xx_hal_config_sta_params_v1 *v1)
1125 {
1126 	/* convert orig to v1 format */
1127 	memcpy(&v1->bssid, orig->bssid, ETH_ALEN);
1128 	memcpy(&v1->mac, orig->mac, ETH_ALEN);
1129 	v1->aid = orig->aid;
1130 	v1->type = orig->type;
1131 	v1->short_preamble_supported = orig->short_preamble_supported;
1132 	v1->listen_interval = orig->listen_interval;
1133 	v1->wmm_enabled = orig->wmm_enabled;
1134 	v1->ht_capable = orig->ht_capable;
1135 	v1->tx_channel_width_set = orig->tx_channel_width_set;
1136 	v1->rifs_mode = orig->rifs_mode;
1137 	v1->lsig_txop_protection = orig->lsig_txop_protection;
1138 	v1->max_ampdu_size = orig->max_ampdu_size;
1139 	v1->max_ampdu_density = orig->max_ampdu_density;
1140 	v1->sgi_40mhz = orig->sgi_40mhz;
1141 	v1->sgi_20Mhz = orig->sgi_20Mhz;
1142 	v1->rmf = orig->rmf;
1143 	v1->encrypt_type = orig->encrypt_type;
1144 	v1->action = orig->action;
1145 	v1->uapsd = orig->uapsd;
1146 	v1->max_sp_len = orig->max_sp_len;
1147 	v1->green_field_capable = orig->green_field_capable;
1148 	v1->mimo_ps = orig->mimo_ps;
1149 	v1->delayed_ba_support = orig->delayed_ba_support;
1150 	v1->max_ampdu_duration = orig->max_ampdu_duration;
1151 	v1->dsss_cck_mode_40mhz = orig->dsss_cck_mode_40mhz;
1152 	memcpy(&v1->supported_rates, &orig->supported_rates,
1153 	       sizeof(orig->supported_rates));
1154 	v1->sta_index = orig->sta_index;
1155 	v1->bssid_index = orig->bssid_index;
1156 	v1->p2p = orig->p2p;
1157 }
1158 
1159 static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
1160 				      struct ieee80211_sta *sta,
1161 				      void *buf,
1162 				      size_t len)
1163 {
1164 	struct wcn36xx_hal_config_sta_rsp_msg *rsp;
1165 	struct config_sta_rsp_params *params;
1166 	struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1167 
1168 	if (len < sizeof(*rsp))
1169 		return -EINVAL;
1170 
1171 	rsp = (struct wcn36xx_hal_config_sta_rsp_msg *)buf;
1172 	params = &rsp->params;
1173 
1174 	if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1175 		wcn36xx_warn("hal config sta response failure: %d\n",
1176 			     params->status);
1177 		return -EIO;
1178 	}
1179 
1180 	sta_priv->sta_index = params->sta_index;
1181 	sta_priv->dpu_desc_index = params->dpu_index;
1182 	sta_priv->ucast_dpu_sign = params->uc_ucast_sig;
1183 
1184 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1185 		    "hal config sta rsp status %d sta_index %d bssid_index %d uc_ucast_sig %d p2p %d\n",
1186 		    params->status, params->sta_index, params->bssid_index,
1187 		    params->uc_ucast_sig, params->p2p);
1188 
1189 	return 0;
1190 }
1191 
1192 static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn,
1193 		     const struct wcn36xx_hal_config_sta_req_msg *orig)
1194 {
1195 	struct wcn36xx_hal_config_sta_req_msg_v1 msg_body;
1196 	struct wcn36xx_hal_config_sta_params_v1 *sta = &msg_body.sta_params;
1197 
1198 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
1199 
1200 	wcn36xx_smd_convert_sta_to_v1(wcn, &orig->sta_params,
1201 				      &msg_body.sta_params);
1202 
1203 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1204 
1205 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1206 		    "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1207 		    sta->action, sta->sta_index, sta->bssid_index,
1208 		    sta->bssid, sta->type, sta->mac, sta->aid);
1209 
1210 	return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1211 }
1212 
1213 int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1214 			   struct ieee80211_sta *sta)
1215 {
1216 	struct wcn36xx_hal_config_sta_req_msg msg;
1217 	struct wcn36xx_hal_config_sta_params *sta_params;
1218 	int ret = 0;
1219 
1220 	mutex_lock(&wcn->hal_mutex);
1221 	INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ);
1222 
1223 	sta_params = &msg.sta_params;
1224 
1225 	wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1226 
1227 	if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
1228 		ret = wcn36xx_smd_config_sta_v1(wcn, &msg);
1229 	} else {
1230 		PREPARE_HAL_BUF(wcn->hal_buf, msg);
1231 
1232 		wcn36xx_dbg(WCN36XX_DBG_HAL,
1233 			    "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1234 			    sta_params->action, sta_params->sta_index,
1235 			    sta_params->bssid_index, sta_params->bssid,
1236 			    sta_params->type, sta_params->mac, sta_params->aid);
1237 
1238 		ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1239 	}
1240 	if (ret) {
1241 		wcn36xx_err("Sending hal_config_sta failed\n");
1242 		goto out;
1243 	}
1244 	ret = wcn36xx_smd_config_sta_rsp(wcn,
1245 					 sta,
1246 					 wcn->hal_buf,
1247 					 wcn->hal_rsp_len);
1248 	if (ret) {
1249 		wcn36xx_err("hal_config_sta response failed err=%d\n", ret);
1250 		goto out;
1251 	}
1252 out:
1253 	mutex_unlock(&wcn->hal_mutex);
1254 	return ret;
1255 }
1256 
1257 static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
1258 			const struct wcn36xx_hal_config_bss_req_msg *orig)
1259 {
1260 	struct wcn36xx_hal_config_bss_req_msg_v1 msg_body;
1261 	struct wcn36xx_hal_config_bss_params_v1 *bss = &msg_body.bss_params;
1262 	struct wcn36xx_hal_config_sta_params_v1 *sta = &bss->sta;
1263 
1264 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_BSS_REQ);
1265 
1266 	/* convert orig to v1 */
1267 	memcpy(&msg_body.bss_params.bssid,
1268 	       &orig->bss_params.bssid, ETH_ALEN);
1269 	memcpy(&msg_body.bss_params.self_mac_addr,
1270 	       &orig->bss_params.self_mac_addr, ETH_ALEN);
1271 
1272 	msg_body.bss_params.bss_type = orig->bss_params.bss_type;
1273 	msg_body.bss_params.oper_mode = orig->bss_params.oper_mode;
1274 	msg_body.bss_params.nw_type = orig->bss_params.nw_type;
1275 
1276 	msg_body.bss_params.short_slot_time_supported =
1277 		orig->bss_params.short_slot_time_supported;
1278 	msg_body.bss_params.lla_coexist = orig->bss_params.lla_coexist;
1279 	msg_body.bss_params.llb_coexist = orig->bss_params.llb_coexist;
1280 	msg_body.bss_params.llg_coexist = orig->bss_params.llg_coexist;
1281 	msg_body.bss_params.ht20_coexist = orig->bss_params.ht20_coexist;
1282 	msg_body.bss_params.lln_non_gf_coexist =
1283 		orig->bss_params.lln_non_gf_coexist;
1284 
1285 	msg_body.bss_params.lsig_tx_op_protection_full_support =
1286 		orig->bss_params.lsig_tx_op_protection_full_support;
1287 	msg_body.bss_params.rifs_mode = orig->bss_params.rifs_mode;
1288 	msg_body.bss_params.beacon_interval = orig->bss_params.beacon_interval;
1289 	msg_body.bss_params.dtim_period = orig->bss_params.dtim_period;
1290 	msg_body.bss_params.tx_channel_width_set =
1291 		orig->bss_params.tx_channel_width_set;
1292 	msg_body.bss_params.oper_channel = orig->bss_params.oper_channel;
1293 	msg_body.bss_params.ext_channel = orig->bss_params.ext_channel;
1294 
1295 	msg_body.bss_params.reserved = orig->bss_params.reserved;
1296 
1297 	memcpy(&msg_body.bss_params.ssid,
1298 	       &orig->bss_params.ssid,
1299 	       sizeof(orig->bss_params.ssid));
1300 
1301 	msg_body.bss_params.action = orig->bss_params.action;
1302 	msg_body.bss_params.rateset = orig->bss_params.rateset;
1303 	msg_body.bss_params.ht = orig->bss_params.ht;
1304 	msg_body.bss_params.obss_prot_enabled =
1305 		orig->bss_params.obss_prot_enabled;
1306 	msg_body.bss_params.rmf = orig->bss_params.rmf;
1307 	msg_body.bss_params.ht_oper_mode = orig->bss_params.ht_oper_mode;
1308 	msg_body.bss_params.dual_cts_protection =
1309 		orig->bss_params.dual_cts_protection;
1310 
1311 	msg_body.bss_params.max_probe_resp_retry_limit =
1312 		orig->bss_params.max_probe_resp_retry_limit;
1313 	msg_body.bss_params.hidden_ssid = orig->bss_params.hidden_ssid;
1314 	msg_body.bss_params.proxy_probe_resp =
1315 		orig->bss_params.proxy_probe_resp;
1316 	msg_body.bss_params.edca_params_valid =
1317 		orig->bss_params.edca_params_valid;
1318 
1319 	memcpy(&msg_body.bss_params.acbe,
1320 	       &orig->bss_params.acbe,
1321 	       sizeof(orig->bss_params.acbe));
1322 	memcpy(&msg_body.bss_params.acbk,
1323 	       &orig->bss_params.acbk,
1324 	       sizeof(orig->bss_params.acbk));
1325 	memcpy(&msg_body.bss_params.acvi,
1326 	       &orig->bss_params.acvi,
1327 	       sizeof(orig->bss_params.acvi));
1328 	memcpy(&msg_body.bss_params.acvo,
1329 	       &orig->bss_params.acvo,
1330 	       sizeof(orig->bss_params.acvo));
1331 
1332 	msg_body.bss_params.ext_set_sta_key_param_valid =
1333 		orig->bss_params.ext_set_sta_key_param_valid;
1334 
1335 	memcpy(&msg_body.bss_params.ext_set_sta_key_param,
1336 	       &orig->bss_params.ext_set_sta_key_param,
1337 	       sizeof(orig->bss_params.acvo));
1338 
1339 	msg_body.bss_params.wcn36xx_hal_persona =
1340 		orig->bss_params.wcn36xx_hal_persona;
1341 	msg_body.bss_params.spectrum_mgt_enable =
1342 		orig->bss_params.spectrum_mgt_enable;
1343 	msg_body.bss_params.tx_mgmt_power = orig->bss_params.tx_mgmt_power;
1344 	msg_body.bss_params.max_tx_power = orig->bss_params.max_tx_power;
1345 
1346 	wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta,
1347 				      &msg_body.bss_params.sta);
1348 
1349 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1350 
1351 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1352 		    "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1353 		    bss->bssid, bss->self_mac_addr, bss->bss_type,
1354 		    bss->oper_mode, bss->nw_type);
1355 
1356 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1357 		    "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1358 		    sta->bssid, sta->action, sta->sta_index,
1359 		    sta->bssid_index, sta->aid, sta->type, sta->mac);
1360 
1361 	return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1362 }
1363 
1364 
1365 static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
1366 				      struct ieee80211_vif *vif,
1367 				      struct ieee80211_sta *sta,
1368 				      void *buf,
1369 				      size_t len)
1370 {
1371 	struct wcn36xx_hal_config_bss_rsp_msg *rsp;
1372 	struct wcn36xx_hal_config_bss_rsp_params *params;
1373 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1374 
1375 	if (len < sizeof(*rsp))
1376 		return -EINVAL;
1377 
1378 	rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf;
1379 	params = &rsp->bss_rsp_params;
1380 
1381 	if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1382 		wcn36xx_warn("hal config bss response failure: %d\n",
1383 			     params->status);
1384 		return -EIO;
1385 	}
1386 
1387 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1388 		    "hal config bss rsp status %d bss_idx %d dpu_desc_index %d"
1389 		    " sta_idx %d self_idx %d bcast_idx %d mac %pM"
1390 		    " power %d ucast_dpu_signature %d\n",
1391 		    params->status, params->bss_index, params->dpu_desc_index,
1392 		    params->bss_sta_index, params->bss_self_sta_index,
1393 		    params->bss_bcast_sta_idx, params->mac,
1394 		    params->tx_mgmt_power, params->ucast_dpu_signature);
1395 
1396 	vif_priv->bss_index = params->bss_index;
1397 
1398 	if (sta) {
1399 		struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1400 		sta_priv->bss_sta_index = params->bss_sta_index;
1401 		sta_priv->bss_dpu_desc_index = params->dpu_desc_index;
1402 	}
1403 
1404 	vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature;
1405 
1406 	return 0;
1407 }
1408 
1409 int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1410 			   struct ieee80211_sta *sta, const u8 *bssid,
1411 			   bool update)
1412 {
1413 	struct wcn36xx_hal_config_bss_req_msg msg;
1414 	struct wcn36xx_hal_config_bss_params *bss;
1415 	struct wcn36xx_hal_config_sta_params *sta_params;
1416 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1417 	int ret = 0;
1418 
1419 	mutex_lock(&wcn->hal_mutex);
1420 	INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_BSS_REQ);
1421 
1422 	bss = &msg.bss_params;
1423 	sta_params = &bss->sta;
1424 
1425 	WARN_ON(is_zero_ether_addr(bssid));
1426 
1427 	memcpy(&bss->bssid, bssid, ETH_ALEN);
1428 
1429 	memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN);
1430 
1431 	if (vif->type == NL80211_IFTYPE_STATION) {
1432 		bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE;
1433 
1434 		/* STA */
1435 		bss->oper_mode = 1;
1436 		bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE;
1437 	} else if (vif->type == NL80211_IFTYPE_AP ||
1438 		   vif->type == NL80211_IFTYPE_MESH_POINT) {
1439 		bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE;
1440 
1441 		/* AP */
1442 		bss->oper_mode = 0;
1443 		bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE;
1444 	} else if (vif->type == NL80211_IFTYPE_ADHOC) {
1445 		bss->bss_type = WCN36XX_HAL_IBSS_MODE;
1446 
1447 		/* STA */
1448 		bss->oper_mode = 1;
1449 	} else {
1450 		wcn36xx_warn("Unknown type for bss config: %d\n", vif->type);
1451 	}
1452 
1453 	if (vif->type == NL80211_IFTYPE_STATION)
1454 		wcn36xx_smd_set_bss_nw_type(wcn, sta, bss);
1455 	else
1456 		bss->nw_type = WCN36XX_HAL_11N_NW_TYPE;
1457 
1458 	bss->short_slot_time_supported = vif->bss_conf.use_short_slot;
1459 	bss->lla_coexist = 0;
1460 	bss->llb_coexist = 0;
1461 	bss->llg_coexist = 0;
1462 	bss->rifs_mode = 0;
1463 	bss->beacon_interval = vif->bss_conf.beacon_int;
1464 	bss->dtim_period = vif_priv->dtim_period;
1465 
1466 	wcn36xx_smd_set_bss_ht_params(vif, sta, bss);
1467 
1468 	bss->oper_channel = WCN36XX_HW_CHANNEL(wcn);
1469 
1470 	if (conf_is_ht40_minus(&wcn->hw->conf))
1471 		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
1472 	else if (conf_is_ht40_plus(&wcn->hw->conf))
1473 		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
1474 	else
1475 		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE;
1476 
1477 	bss->reserved = 0;
1478 	wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1479 
1480 	/* wcn->ssid is only valid in AP and IBSS mode */
1481 	bss->ssid.length = vif_priv->ssid.length;
1482 	memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length);
1483 
1484 	bss->obss_prot_enabled = 0;
1485 	bss->rmf = 0;
1486 	bss->max_probe_resp_retry_limit = 0;
1487 	bss->hidden_ssid = vif->bss_conf.hidden_ssid;
1488 	bss->proxy_probe_resp = 0;
1489 	bss->edca_params_valid = 0;
1490 
1491 	/* FIXME: set acbe, acbk, acvi and acvo */
1492 
1493 	bss->ext_set_sta_key_param_valid = 0;
1494 
1495 	/* FIXME: set ext_set_sta_key_param */
1496 
1497 	bss->spectrum_mgt_enable = 0;
1498 	bss->tx_mgmt_power = 0;
1499 	bss->max_tx_power = WCN36XX_MAX_POWER(wcn);
1500 	bss->action = update;
1501 
1502 	vif_priv->bss_type = bss->bss_type;
1503 
1504 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1505 		    "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1506 		    bss->bssid, bss->self_mac_addr, bss->bss_type,
1507 		    bss->oper_mode, bss->nw_type);
1508 
1509 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1510 		    "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1511 		    sta_params->bssid, sta_params->action,
1512 		    sta_params->sta_index, sta_params->bssid_index,
1513 		    sta_params->aid, sta_params->type,
1514 		    sta_params->mac);
1515 
1516 	if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
1517 		ret = wcn36xx_smd_config_bss_v1(wcn, &msg);
1518 	} else {
1519 		PREPARE_HAL_BUF(wcn->hal_buf, msg);
1520 
1521 		ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1522 	}
1523 	if (ret) {
1524 		wcn36xx_err("Sending hal_config_bss failed\n");
1525 		goto out;
1526 	}
1527 	ret = wcn36xx_smd_config_bss_rsp(wcn,
1528 					 vif,
1529 					 sta,
1530 					 wcn->hal_buf,
1531 					 wcn->hal_rsp_len);
1532 	if (ret) {
1533 		wcn36xx_err("hal_config_bss response failed err=%d\n", ret);
1534 		goto out;
1535 	}
1536 out:
1537 	mutex_unlock(&wcn->hal_mutex);
1538 	return ret;
1539 }
1540 
1541 int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1542 {
1543 	struct wcn36xx_hal_delete_bss_req_msg msg_body;
1544 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1545 	int ret = 0;
1546 
1547 	mutex_lock(&wcn->hal_mutex);
1548 
1549 	if (vif_priv->bss_index == WCN36XX_HAL_BSS_INVALID_IDX)
1550 		goto out;
1551 
1552 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ);
1553 
1554 	msg_body.bss_index = vif_priv->bss_index;
1555 
1556 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1557 
1558 	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index);
1559 
1560 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1561 	if (ret) {
1562 		wcn36xx_err("Sending hal_delete_bss failed\n");
1563 		goto out;
1564 	}
1565 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1566 	if (ret) {
1567 		wcn36xx_err("hal_delete_bss response failed err=%d\n", ret);
1568 		goto out;
1569 	}
1570 
1571 	vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
1572 out:
1573 	mutex_unlock(&wcn->hal_mutex);
1574 	return ret;
1575 }
1576 
1577 int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1578 			    struct sk_buff *skb_beacon, u16 tim_off,
1579 			    u16 p2p_off)
1580 {
1581 	struct wcn36xx_hal_send_beacon_req_msg msg_body;
1582 	int ret = 0, pad, pvm_len;
1583 
1584 	mutex_lock(&wcn->hal_mutex);
1585 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
1586 
1587 	pvm_len = skb_beacon->data[tim_off + 1] - 3;
1588 	pad = TIM_MIN_PVM_SIZE - pvm_len;
1589 
1590 	/* Padding is irrelevant to mesh mode since tim_off is always 0. */
1591 	if (vif->type == NL80211_IFTYPE_MESH_POINT)
1592 		pad = 0;
1593 
1594 	msg_body.beacon_length = skb_beacon->len + pad;
1595 	/* TODO need to find out why + 6 is needed */
1596 	msg_body.beacon_length6 = msg_body.beacon_length + 6;
1597 
1598 	if (msg_body.beacon_length > BEACON_TEMPLATE_SIZE) {
1599 		wcn36xx_err("Beacon is to big: beacon size=%d\n",
1600 			      msg_body.beacon_length);
1601 		ret = -ENOMEM;
1602 		goto out;
1603 	}
1604 	memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len);
1605 	memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
1606 
1607 	if (pad > 0) {
1608 		/*
1609 		 * The wcn36xx FW has a fixed size for the PVM in the TIM. If
1610 		 * given the beacon template from mac80211 with a PVM shorter
1611 		 * than the FW expectes it will overwrite the data after the
1612 		 * TIM.
1613 		 */
1614 		wcn36xx_dbg(WCN36XX_DBG_HAL, "Pad TIM PVM. %d bytes at %d\n",
1615 			    pad, pvm_len);
1616 		memmove(&msg_body.beacon[tim_off + 5 + pvm_len + pad],
1617 			&msg_body.beacon[tim_off + 5 + pvm_len],
1618 			skb_beacon->len - (tim_off + 5 + pvm_len));
1619 		memset(&msg_body.beacon[tim_off + 5 + pvm_len], 0, pad);
1620 		msg_body.beacon[tim_off + 1] += pad;
1621 	}
1622 
1623 	/* TODO need to find out why this is needed? */
1624 	if (vif->type == NL80211_IFTYPE_MESH_POINT)
1625 		/* mesh beacon don't need this, so push further down */
1626 		msg_body.tim_ie_offset = 256;
1627 	else
1628 		msg_body.tim_ie_offset = tim_off+4;
1629 	msg_body.p2p_ie_offset = p2p_off;
1630 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1631 
1632 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1633 		    "hal send beacon beacon_length %d\n",
1634 		    msg_body.beacon_length);
1635 
1636 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1637 	if (ret) {
1638 		wcn36xx_err("Sending hal_send_beacon failed\n");
1639 		goto out;
1640 	}
1641 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1642 	if (ret) {
1643 		wcn36xx_err("hal_send_beacon response failed err=%d\n", ret);
1644 		goto out;
1645 	}
1646 out:
1647 	mutex_unlock(&wcn->hal_mutex);
1648 	return ret;
1649 }
1650 
1651 int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn,
1652 				      struct ieee80211_vif *vif,
1653 				      struct sk_buff *skb)
1654 {
1655 	struct wcn36xx_hal_send_probe_resp_req_msg msg;
1656 	int ret = 0;
1657 
1658 	mutex_lock(&wcn->hal_mutex);
1659 	INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ);
1660 
1661 	if (skb->len > BEACON_TEMPLATE_SIZE) {
1662 		wcn36xx_warn("probe response template is too big: %d\n",
1663 			     skb->len);
1664 		ret = -E2BIG;
1665 		goto out;
1666 	}
1667 
1668 	msg.probe_resp_template_len = skb->len;
1669 	memcpy(&msg.probe_resp_template, skb->data, skb->len);
1670 
1671 	memcpy(msg.bssid, vif->addr, ETH_ALEN);
1672 
1673 	PREPARE_HAL_BUF(wcn->hal_buf, msg);
1674 
1675 	wcn36xx_dbg(WCN36XX_DBG_HAL,
1676 		    "hal update probe rsp len %d bssid %pM\n",
1677 		    msg.probe_resp_template_len, msg.bssid);
1678 
1679 	ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1680 	if (ret) {
1681 		wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n");
1682 		goto out;
1683 	}
1684 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1685 	if (ret) {
1686 		wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n",
1687 			    ret);
1688 		goto out;
1689 	}
1690 out:
1691 	mutex_unlock(&wcn->hal_mutex);
1692 	return ret;
1693 }
1694 
1695 int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
1696 			   enum ani_ed_type enc_type,
1697 			   u8 keyidx,
1698 			   u8 keylen,
1699 			   u8 *key,
1700 			   u8 sta_index)
1701 {
1702 	struct wcn36xx_hal_set_sta_key_req_msg msg_body;
1703 	int ret = 0;
1704 
1705 	mutex_lock(&wcn->hal_mutex);
1706 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ);
1707 
1708 	msg_body.set_sta_key_params.sta_index = sta_index;
1709 	msg_body.set_sta_key_params.enc_type = enc_type;
1710 
1711 	msg_body.set_sta_key_params.key[0].id = keyidx;
1712 	msg_body.set_sta_key_params.key[0].unicast = 1;
1713 	msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
1714 	msg_body.set_sta_key_params.key[0].pae_role = 0;
1715 	msg_body.set_sta_key_params.key[0].length = keylen;
1716 	memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
1717 	msg_body.set_sta_key_params.single_tid_rc = 1;
1718 
1719 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1720 
1721 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1722 	if (ret) {
1723 		wcn36xx_err("Sending hal_set_stakey failed\n");
1724 		goto out;
1725 	}
1726 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1727 	if (ret) {
1728 		wcn36xx_err("hal_set_stakey response failed err=%d\n", ret);
1729 		goto out;
1730 	}
1731 out:
1732 	mutex_unlock(&wcn->hal_mutex);
1733 	return ret;
1734 }
1735 
1736 int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn,
1737 			   enum ani_ed_type enc_type,
1738 			   u8 bssidx,
1739 			   u8 keyidx,
1740 			   u8 keylen,
1741 			   u8 *key)
1742 {
1743 	struct wcn36xx_hal_set_bss_key_req_msg msg_body;
1744 	int ret = 0;
1745 
1746 	mutex_lock(&wcn->hal_mutex);
1747 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ);
1748 	msg_body.bss_idx = bssidx;
1749 	msg_body.enc_type = enc_type;
1750 	msg_body.num_keys = 1;
1751 	msg_body.keys[0].id = keyidx;
1752 	msg_body.keys[0].unicast = 0;
1753 	msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY;
1754 	msg_body.keys[0].pae_role = 0;
1755 	msg_body.keys[0].length = keylen;
1756 	memcpy(msg_body.keys[0].key, key, keylen);
1757 
1758 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1759 
1760 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1761 	if (ret) {
1762 		wcn36xx_err("Sending hal_set_bsskey failed\n");
1763 		goto out;
1764 	}
1765 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1766 	if (ret) {
1767 		wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret);
1768 		goto out;
1769 	}
1770 out:
1771 	mutex_unlock(&wcn->hal_mutex);
1772 	return ret;
1773 }
1774 
1775 int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn,
1776 			      enum ani_ed_type enc_type,
1777 			      u8 keyidx,
1778 			      u8 sta_index)
1779 {
1780 	struct wcn36xx_hal_remove_sta_key_req_msg msg_body;
1781 	int ret = 0;
1782 
1783 	mutex_lock(&wcn->hal_mutex);
1784 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ);
1785 
1786 	msg_body.sta_idx = sta_index;
1787 	msg_body.enc_type = enc_type;
1788 	msg_body.key_id = keyidx;
1789 
1790 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1791 
1792 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1793 	if (ret) {
1794 		wcn36xx_err("Sending hal_remove_stakey failed\n");
1795 		goto out;
1796 	}
1797 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1798 	if (ret) {
1799 		wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret);
1800 		goto out;
1801 	}
1802 out:
1803 	mutex_unlock(&wcn->hal_mutex);
1804 	return ret;
1805 }
1806 
1807 int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
1808 			      enum ani_ed_type enc_type,
1809 			      u8 bssidx,
1810 			      u8 keyidx)
1811 {
1812 	struct wcn36xx_hal_remove_bss_key_req_msg msg_body;
1813 	int ret = 0;
1814 
1815 	mutex_lock(&wcn->hal_mutex);
1816 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ);
1817 	msg_body.bss_idx = bssidx;
1818 	msg_body.enc_type = enc_type;
1819 	msg_body.key_id = keyidx;
1820 
1821 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1822 
1823 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1824 	if (ret) {
1825 		wcn36xx_err("Sending hal_remove_bsskey failed\n");
1826 		goto out;
1827 	}
1828 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1829 	if (ret) {
1830 		wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
1831 		goto out;
1832 	}
1833 out:
1834 	mutex_unlock(&wcn->hal_mutex);
1835 	return ret;
1836 }
1837 
1838 int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1839 {
1840 	struct wcn36xx_hal_enter_bmps_req_msg msg_body;
1841 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1842 	int ret = 0;
1843 
1844 	mutex_lock(&wcn->hal_mutex);
1845 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ);
1846 
1847 	msg_body.bss_index = vif_priv->bss_index;
1848 	msg_body.tbtt = vif->bss_conf.sync_tsf;
1849 	msg_body.dtim_period = vif_priv->dtim_period;
1850 
1851 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1852 
1853 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1854 	if (ret) {
1855 		wcn36xx_err("Sending hal_enter_bmps failed\n");
1856 		goto out;
1857 	}
1858 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1859 	if (ret) {
1860 		wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret);
1861 		goto out;
1862 	}
1863 out:
1864 	mutex_unlock(&wcn->hal_mutex);
1865 	return ret;
1866 }
1867 
1868 int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1869 {
1870 	struct wcn36xx_hal_exit_bmps_req_msg msg_body;
1871 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1872 	int ret = 0;
1873 
1874 	mutex_lock(&wcn->hal_mutex);
1875 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ);
1876 
1877 	msg_body.bss_index = vif_priv->bss_index;
1878 
1879 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1880 
1881 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1882 	if (ret) {
1883 		wcn36xx_err("Sending hal_exit_bmps failed\n");
1884 		goto out;
1885 	}
1886 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1887 	if (ret) {
1888 		wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
1889 		goto out;
1890 	}
1891 out:
1892 	mutex_unlock(&wcn->hal_mutex);
1893 	return ret;
1894 }
1895 int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim)
1896 {
1897 	struct wcn36xx_hal_set_power_params_req_msg msg_body;
1898 	int ret = 0;
1899 
1900 	mutex_lock(&wcn->hal_mutex);
1901 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ);
1902 
1903 	/*
1904 	 * When host is down ignore every second dtim
1905 	 */
1906 	if (ignore_dtim) {
1907 		msg_body.ignore_dtim = 1;
1908 		msg_body.dtim_period = 2;
1909 	}
1910 	msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
1911 
1912 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1913 
1914 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1915 	if (ret) {
1916 		wcn36xx_err("Sending hal_set_power_params failed\n");
1917 		goto out;
1918 	}
1919 
1920 out:
1921 	mutex_unlock(&wcn->hal_mutex);
1922 	return ret;
1923 }
1924 /* Notice: This function should be called after associated, or else it
1925  * will be invalid
1926  */
1927 int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
1928 			       struct ieee80211_vif *vif,
1929 			       int packet_type)
1930 {
1931 	struct wcn36xx_hal_keep_alive_req_msg msg_body;
1932 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1933 	int ret = 0;
1934 
1935 	mutex_lock(&wcn->hal_mutex);
1936 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ);
1937 
1938 	if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) {
1939 		msg_body.bss_index = vif_priv->bss_index;
1940 		msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT;
1941 		msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD;
1942 	} else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) {
1943 		/* TODO: it also support ARP response type */
1944 	} else {
1945 		wcn36xx_warn("unknown keep alive packet type %d\n", packet_type);
1946 		ret = -EINVAL;
1947 		goto out;
1948 	}
1949 
1950 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1951 
1952 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1953 	if (ret) {
1954 		wcn36xx_err("Sending hal_keep_alive failed\n");
1955 		goto out;
1956 	}
1957 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1958 	if (ret) {
1959 		wcn36xx_err("hal_keep_alive response failed err=%d\n", ret);
1960 		goto out;
1961 	}
1962 out:
1963 	mutex_unlock(&wcn->hal_mutex);
1964 	return ret;
1965 }
1966 
1967 int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
1968 			     u32 arg3, u32 arg4, u32 arg5)
1969 {
1970 	struct wcn36xx_hal_dump_cmd_req_msg msg_body;
1971 	int ret = 0;
1972 
1973 	mutex_lock(&wcn->hal_mutex);
1974 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ);
1975 
1976 	msg_body.arg1 = arg1;
1977 	msg_body.arg2 = arg2;
1978 	msg_body.arg3 = arg3;
1979 	msg_body.arg4 = arg4;
1980 	msg_body.arg5 = arg5;
1981 
1982 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1983 
1984 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1985 	if (ret) {
1986 		wcn36xx_err("Sending hal_dump_cmd failed\n");
1987 		goto out;
1988 	}
1989 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1990 	if (ret) {
1991 		wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret);
1992 		goto out;
1993 	}
1994 out:
1995 	mutex_unlock(&wcn->hal_mutex);
1996 	return ret;
1997 }
1998 
1999 void set_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
2000 {
2001 	int arr_idx, bit_idx;
2002 
2003 	if (cap < 0 || cap > 127) {
2004 		wcn36xx_warn("error cap idx %d\n", cap);
2005 		return;
2006 	}
2007 
2008 	arr_idx = cap / 32;
2009 	bit_idx = cap % 32;
2010 	bitmap[arr_idx] |= (1 << bit_idx);
2011 }
2012 
2013 int get_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
2014 {
2015 	int arr_idx, bit_idx;
2016 	int ret = 0;
2017 
2018 	if (cap < 0 || cap > 127) {
2019 		wcn36xx_warn("error cap idx %d\n", cap);
2020 		return -EINVAL;
2021 	}
2022 
2023 	arr_idx = cap / 32;
2024 	bit_idx = cap % 32;
2025 	ret = (bitmap[arr_idx] & (1 << bit_idx)) ? 1 : 0;
2026 	return ret;
2027 }
2028 
2029 void clear_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
2030 {
2031 	int arr_idx, bit_idx;
2032 
2033 	if (cap < 0 || cap > 127) {
2034 		wcn36xx_warn("error cap idx %d\n", cap);
2035 		return;
2036 	}
2037 
2038 	arr_idx = cap / 32;
2039 	bit_idx = cap % 32;
2040 	bitmap[arr_idx] &= ~(1 << bit_idx);
2041 }
2042 
2043 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
2044 {
2045 	struct wcn36xx_hal_feat_caps_msg msg_body, *rsp;
2046 	int ret = 0, i;
2047 
2048 	mutex_lock(&wcn->hal_mutex);
2049 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
2050 
2051 	set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
2052 
2053 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2054 
2055 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2056 	if (ret) {
2057 		wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
2058 		goto out;
2059 	}
2060 	if (wcn->hal_rsp_len != sizeof(*rsp)) {
2061 		wcn36xx_err("Invalid hal_feature_caps_exchange response");
2062 		goto out;
2063 	}
2064 
2065 	rsp = (struct wcn36xx_hal_feat_caps_msg *) wcn->hal_buf;
2066 
2067 	for (i = 0; i < WCN36XX_HAL_CAPS_SIZE; i++)
2068 		wcn->fw_feat_caps[i] = rsp->feat_caps[i];
2069 out:
2070 	mutex_unlock(&wcn->hal_mutex);
2071 	return ret;
2072 }
2073 
2074 int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
2075 		struct ieee80211_sta *sta,
2076 		u16 tid,
2077 		u16 *ssn,
2078 		u8 direction,
2079 		u8 sta_index)
2080 {
2081 	struct wcn36xx_hal_add_ba_session_req_msg msg_body;
2082 	int ret = 0;
2083 
2084 	mutex_lock(&wcn->hal_mutex);
2085 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ);
2086 
2087 	msg_body.sta_index = sta_index;
2088 	memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN);
2089 	msg_body.dialog_token = 0x10;
2090 	msg_body.tid = tid;
2091 
2092 	/* Immediate BA because Delayed BA is not supported */
2093 	msg_body.policy = 1;
2094 	msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE;
2095 	msg_body.timeout = 0;
2096 	if (ssn)
2097 		msg_body.ssn = *ssn;
2098 	msg_body.direction = direction;
2099 
2100 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2101 
2102 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2103 	if (ret) {
2104 		wcn36xx_err("Sending hal_add_ba_session failed\n");
2105 		goto out;
2106 	}
2107 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2108 	if (ret) {
2109 		wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret);
2110 		goto out;
2111 	}
2112 out:
2113 	mutex_unlock(&wcn->hal_mutex);
2114 	return ret;
2115 }
2116 
2117 int wcn36xx_smd_add_ba(struct wcn36xx *wcn)
2118 {
2119 	struct wcn36xx_hal_add_ba_req_msg msg_body;
2120 	int ret = 0;
2121 
2122 	mutex_lock(&wcn->hal_mutex);
2123 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ);
2124 
2125 	msg_body.session_id = 0;
2126 	msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE;
2127 
2128 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2129 
2130 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2131 	if (ret) {
2132 		wcn36xx_err("Sending hal_add_ba failed\n");
2133 		goto out;
2134 	}
2135 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2136 	if (ret) {
2137 		wcn36xx_err("hal_add_ba response failed err=%d\n", ret);
2138 		goto out;
2139 	}
2140 out:
2141 	mutex_unlock(&wcn->hal_mutex);
2142 	return ret;
2143 }
2144 
2145 int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index)
2146 {
2147 	struct wcn36xx_hal_del_ba_req_msg msg_body;
2148 	int ret = 0;
2149 
2150 	mutex_lock(&wcn->hal_mutex);
2151 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ);
2152 
2153 	msg_body.sta_index = sta_index;
2154 	msg_body.tid = tid;
2155 	msg_body.direction = 0;
2156 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2157 
2158 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2159 	if (ret) {
2160 		wcn36xx_err("Sending hal_del_ba failed\n");
2161 		goto out;
2162 	}
2163 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2164 	if (ret) {
2165 		wcn36xx_err("hal_del_ba response failed err=%d\n", ret);
2166 		goto out;
2167 	}
2168 out:
2169 	mutex_unlock(&wcn->hal_mutex);
2170 	return ret;
2171 }
2172 
2173 static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len)
2174 {
2175 	struct wcn36xx_hal_trigger_ba_rsp_msg *rsp;
2176 
2177 	if (len < sizeof(*rsp))
2178 		return -EINVAL;
2179 
2180 	rsp = (struct wcn36xx_hal_trigger_ba_rsp_msg *) buf;
2181 	return rsp->status;
2182 }
2183 
2184 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
2185 {
2186 	struct wcn36xx_hal_trigger_ba_req_msg msg_body;
2187 	struct wcn36xx_hal_trigger_ba_req_candidate *candidate;
2188 	int ret = 0;
2189 
2190 	mutex_lock(&wcn->hal_mutex);
2191 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
2192 
2193 	msg_body.session_id = 0;
2194 	msg_body.candidate_cnt = 1;
2195 	msg_body.header.len += sizeof(*candidate);
2196 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2197 
2198 	candidate = (struct wcn36xx_hal_trigger_ba_req_candidate *)
2199 		(wcn->hal_buf + sizeof(msg_body));
2200 	candidate->sta_index = sta_index;
2201 	candidate->tid_bitmap = 1;
2202 
2203 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2204 	if (ret) {
2205 		wcn36xx_err("Sending hal_trigger_ba failed\n");
2206 		goto out;
2207 	}
2208 	ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len);
2209 	if (ret) {
2210 		wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
2211 		goto out;
2212 	}
2213 out:
2214 	mutex_unlock(&wcn->hal_mutex);
2215 	return ret;
2216 }
2217 
2218 static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len)
2219 {
2220 	struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf;
2221 
2222 	if (len != sizeof(*rsp)) {
2223 		wcn36xx_warn("Bad TX complete indication\n");
2224 		return -EIO;
2225 	}
2226 
2227 	wcn36xx_dxe_tx_ack_ind(wcn, rsp->status);
2228 
2229 	return 0;
2230 }
2231 
2232 static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, void *buf, size_t len)
2233 {
2234 	struct wcn36xx_hal_scan_offload_ind *rsp = buf;
2235 	struct cfg80211_scan_info scan_info = {};
2236 
2237 	if (len != sizeof(*rsp)) {
2238 		wcn36xx_warn("Corrupted delete scan indication\n");
2239 		return -EIO;
2240 	}
2241 
2242 	wcn36xx_dbg(WCN36XX_DBG_HAL, "scan indication (type %x)\n", rsp->type);
2243 
2244 	switch (rsp->type) {
2245 	case WCN36XX_HAL_SCAN_IND_FAILED:
2246 	case WCN36XX_HAL_SCAN_IND_DEQUEUED:
2247 		scan_info.aborted = true;
2248 		/* fall through */
2249 	case WCN36XX_HAL_SCAN_IND_COMPLETED:
2250 		mutex_lock(&wcn->scan_lock);
2251 		wcn->scan_req = NULL;
2252 		if (wcn->scan_aborted)
2253 			scan_info.aborted = true;
2254 		mutex_unlock(&wcn->scan_lock);
2255 		ieee80211_scan_completed(wcn->hw, &scan_info);
2256 		break;
2257 	case WCN36XX_HAL_SCAN_IND_STARTED:
2258 	case WCN36XX_HAL_SCAN_IND_FOREIGN_CHANNEL:
2259 	case WCN36XX_HAL_SCAN_IND_PREEMPTED:
2260 	case WCN36XX_HAL_SCAN_IND_RESTARTED:
2261 		break;
2262 	default:
2263 		wcn36xx_warn("Unknown scan indication type %x\n", rsp->type);
2264 	}
2265 
2266 	return 0;
2267 }
2268 
2269 static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
2270 					 void *buf,
2271 					 size_t len)
2272 {
2273 	struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf;
2274 	struct ieee80211_vif *vif = NULL;
2275 	struct wcn36xx_vif *tmp;
2276 
2277 	/* Old FW does not have bss index */
2278 	if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
2279 		list_for_each_entry(tmp, &wcn->vif_list, list) {
2280 			wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2281 				    tmp->bss_index);
2282 			vif = wcn36xx_priv_to_vif(tmp);
2283 			ieee80211_connection_loss(vif);
2284 		}
2285 		return 0;
2286 	}
2287 
2288 	if (len != sizeof(*rsp)) {
2289 		wcn36xx_warn("Corrupted missed beacon indication\n");
2290 		return -EIO;
2291 	}
2292 
2293 	list_for_each_entry(tmp, &wcn->vif_list, list) {
2294 		if (tmp->bss_index == rsp->bss_index) {
2295 			wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2296 				    rsp->bss_index);
2297 			vif = wcn36xx_priv_to_vif(tmp);
2298 			ieee80211_connection_loss(vif);
2299 			return 0;
2300 		}
2301 	}
2302 
2303 	wcn36xx_warn("BSS index %d not found\n", rsp->bss_index);
2304 	return -ENOENT;
2305 }
2306 
2307 static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
2308 					      void *buf,
2309 					      size_t len)
2310 {
2311 	struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
2312 	struct wcn36xx_vif *tmp;
2313 	struct ieee80211_sta *sta;
2314 
2315 	if (len != sizeof(*rsp)) {
2316 		wcn36xx_warn("Corrupted delete sta indication\n");
2317 		return -EIO;
2318 	}
2319 
2320 	wcn36xx_dbg(WCN36XX_DBG_HAL, "delete station indication %pM index %d\n",
2321 		    rsp->addr2, rsp->sta_id);
2322 
2323 	list_for_each_entry(tmp, &wcn->vif_list, list) {
2324 		rcu_read_lock();
2325 		sta = ieee80211_find_sta(wcn36xx_priv_to_vif(tmp), rsp->addr2);
2326 		if (sta)
2327 			ieee80211_report_low_ack(sta, 0);
2328 		rcu_read_unlock();
2329 		if (sta)
2330 			return 0;
2331 	}
2332 
2333 	wcn36xx_warn("STA with addr %pM and index %d not found\n",
2334 		     rsp->addr2,
2335 		     rsp->sta_id);
2336 	return -ENOENT;
2337 }
2338 
2339 static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn,
2340 					  void *buf,
2341 					  size_t len)
2342 {
2343 	struct wcn36xx_hal_print_reg_info_ind *rsp = buf;
2344 	int i;
2345 
2346 	if (len < sizeof(*rsp)) {
2347 		wcn36xx_warn("Corrupted print reg info indication\n");
2348 		return -EIO;
2349 	}
2350 
2351 	wcn36xx_dbg(WCN36XX_DBG_HAL,
2352 		    "reginfo indication, scenario: 0x%x reason: 0x%x\n",
2353 		    rsp->scenario, rsp->reason);
2354 
2355 	for (i = 0; i < rsp->count; i++) {
2356 		wcn36xx_dbg(WCN36XX_DBG_HAL, "\t0x%x: 0x%x\n",
2357 			    rsp->regs[i].addr, rsp->regs[i].value);
2358 	}
2359 
2360 	return 0;
2361 }
2362 
2363 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
2364 {
2365 	struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
2366 	size_t len;
2367 	int ret = 0;
2368 
2369 	mutex_lock(&wcn->hal_mutex);
2370 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ);
2371 
2372 	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2373 
2374 	body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf;
2375 	len = msg_body.header.len;
2376 
2377 	put_cfg_tlv_u32(wcn, &len, cfg_id, value);
2378 	body->header.len = len;
2379 	body->len = len - sizeof(*body);
2380 
2381 	ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
2382 	if (ret) {
2383 		wcn36xx_err("Sending hal_update_cfg failed\n");
2384 		goto out;
2385 	}
2386 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2387 	if (ret) {
2388 		wcn36xx_err("hal_update_cfg response failed err=%d\n", ret);
2389 		goto out;
2390 	}
2391 out:
2392 	mutex_unlock(&wcn->hal_mutex);
2393 	return ret;
2394 }
2395 
2396 int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
2397 			    struct ieee80211_vif *vif,
2398 			    struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp)
2399 {
2400 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2401 	struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *msg_body = NULL;
2402 	int ret = 0;
2403 
2404 	mutex_lock(&wcn->hal_mutex);
2405 
2406 	msg_body = (struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *)
2407 		   wcn->hal_buf;
2408 	init_hal_msg(&msg_body->header, WCN36XX_HAL_8023_MULTICAST_LIST_REQ,
2409 		     sizeof(msg_body->mc_addr_list));
2410 
2411 	/* An empty list means all mc traffic will be received */
2412 	if (fp)
2413 		memcpy(&msg_body->mc_addr_list, fp,
2414 		       sizeof(msg_body->mc_addr_list));
2415 	else
2416 		msg_body->mc_addr_list.mc_addr_count = 0;
2417 
2418 	msg_body->mc_addr_list.bss_index = vif_priv->bss_index;
2419 
2420 	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
2421 	if (ret) {
2422 		wcn36xx_err("Sending HAL_8023_MULTICAST_LIST failed\n");
2423 		goto out;
2424 	}
2425 	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2426 	if (ret) {
2427 		wcn36xx_err("HAL_8023_MULTICAST_LIST rsp failed err=%d\n", ret);
2428 		goto out;
2429 	}
2430 out:
2431 	mutex_unlock(&wcn->hal_mutex);
2432 	return ret;
2433 }
2434 
2435 int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
2436 			    void *buf, int len, void *priv, u32 addr)
2437 {
2438 	const struct wcn36xx_hal_msg_header *msg_header = buf;
2439 	struct ieee80211_hw *hw = priv;
2440 	struct wcn36xx *wcn = hw->priv;
2441 	struct wcn36xx_hal_ind_msg *msg_ind;
2442 	wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
2443 
2444 	switch (msg_header->msg_type) {
2445 	case WCN36XX_HAL_START_RSP:
2446 	case WCN36XX_HAL_CONFIG_STA_RSP:
2447 	case WCN36XX_HAL_CONFIG_BSS_RSP:
2448 	case WCN36XX_HAL_ADD_STA_SELF_RSP:
2449 	case WCN36XX_HAL_STOP_RSP:
2450 	case WCN36XX_HAL_DEL_STA_SELF_RSP:
2451 	case WCN36XX_HAL_DELETE_STA_RSP:
2452 	case WCN36XX_HAL_INIT_SCAN_RSP:
2453 	case WCN36XX_HAL_START_SCAN_RSP:
2454 	case WCN36XX_HAL_END_SCAN_RSP:
2455 	case WCN36XX_HAL_FINISH_SCAN_RSP:
2456 	case WCN36XX_HAL_DOWNLOAD_NV_RSP:
2457 	case WCN36XX_HAL_DELETE_BSS_RSP:
2458 	case WCN36XX_HAL_SEND_BEACON_RSP:
2459 	case WCN36XX_HAL_SET_LINK_ST_RSP:
2460 	case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP:
2461 	case WCN36XX_HAL_SET_BSSKEY_RSP:
2462 	case WCN36XX_HAL_SET_STAKEY_RSP:
2463 	case WCN36XX_HAL_RMV_STAKEY_RSP:
2464 	case WCN36XX_HAL_RMV_BSSKEY_RSP:
2465 	case WCN36XX_HAL_ENTER_BMPS_RSP:
2466 	case WCN36XX_HAL_SET_POWER_PARAMS_RSP:
2467 	case WCN36XX_HAL_EXIT_BMPS_RSP:
2468 	case WCN36XX_HAL_KEEP_ALIVE_RSP:
2469 	case WCN36XX_HAL_DUMP_COMMAND_RSP:
2470 	case WCN36XX_HAL_ADD_BA_SESSION_RSP:
2471 	case WCN36XX_HAL_ADD_BA_RSP:
2472 	case WCN36XX_HAL_DEL_BA_RSP:
2473 	case WCN36XX_HAL_TRIGGER_BA_RSP:
2474 	case WCN36XX_HAL_UPDATE_CFG_RSP:
2475 	case WCN36XX_HAL_JOIN_RSP:
2476 	case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP:
2477 	case WCN36XX_HAL_CH_SWITCH_RSP:
2478 	case WCN36XX_HAL_PROCESS_PTT_RSP:
2479 	case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
2480 	case WCN36XX_HAL_8023_MULTICAST_LIST_RSP:
2481 	case WCN36XX_HAL_START_SCAN_OFFLOAD_RSP:
2482 	case WCN36XX_HAL_STOP_SCAN_OFFLOAD_RSP:
2483 		memcpy(wcn->hal_buf, buf, len);
2484 		wcn->hal_rsp_len = len;
2485 		complete(&wcn->hal_rsp_compl);
2486 		break;
2487 
2488 	case WCN36XX_HAL_COEX_IND:
2489 	case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
2490 	case WCN36XX_HAL_DEL_BA_IND:
2491 	case WCN36XX_HAL_OTA_TX_COMPL_IND:
2492 	case WCN36XX_HAL_MISSED_BEACON_IND:
2493 	case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
2494 	case WCN36XX_HAL_PRINT_REG_INFO_IND:
2495 	case WCN36XX_HAL_SCAN_OFFLOAD_IND:
2496 		msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_ATOMIC);
2497 		if (!msg_ind) {
2498 			wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
2499 				    msg_header->msg_type);
2500 			return -ENOMEM;
2501 		}
2502 
2503 		msg_ind->msg_len = len;
2504 		memcpy(msg_ind->msg, buf, len);
2505 
2506 		spin_lock(&wcn->hal_ind_lock);
2507 		list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
2508 		queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
2509 		spin_unlock(&wcn->hal_ind_lock);
2510 		wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
2511 		break;
2512 	default:
2513 		wcn36xx_err("SMD_EVENT (%d) not supported\n",
2514 			      msg_header->msg_type);
2515 	}
2516 
2517 	return 0;
2518 }
2519 
2520 static void wcn36xx_ind_smd_work(struct work_struct *work)
2521 {
2522 	struct wcn36xx *wcn =
2523 		container_of(work, struct wcn36xx, hal_ind_work);
2524 
2525 	for (;;) {
2526 		struct wcn36xx_hal_msg_header *msg_header;
2527 		struct wcn36xx_hal_ind_msg *hal_ind_msg;
2528 		unsigned long flags;
2529 
2530 		spin_lock_irqsave(&wcn->hal_ind_lock, flags);
2531 
2532 		if (list_empty(&wcn->hal_ind_queue)) {
2533 			spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
2534 			return;
2535 		}
2536 
2537 		hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
2538 					       struct wcn36xx_hal_ind_msg,
2539 					       list);
2540 		list_del(&hal_ind_msg->list);
2541 		spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
2542 
2543 		msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
2544 
2545 		switch (msg_header->msg_type) {
2546 		case WCN36XX_HAL_COEX_IND:
2547 		case WCN36XX_HAL_DEL_BA_IND:
2548 		case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
2549 			break;
2550 		case WCN36XX_HAL_OTA_TX_COMPL_IND:
2551 			wcn36xx_smd_tx_compl_ind(wcn,
2552 						 hal_ind_msg->msg,
2553 						 hal_ind_msg->msg_len);
2554 			break;
2555 		case WCN36XX_HAL_MISSED_BEACON_IND:
2556 			wcn36xx_smd_missed_beacon_ind(wcn,
2557 						      hal_ind_msg->msg,
2558 						      hal_ind_msg->msg_len);
2559 			break;
2560 		case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
2561 			wcn36xx_smd_delete_sta_context_ind(wcn,
2562 							   hal_ind_msg->msg,
2563 							   hal_ind_msg->msg_len);
2564 			break;
2565 		case WCN36XX_HAL_PRINT_REG_INFO_IND:
2566 			wcn36xx_smd_print_reg_info_ind(wcn,
2567 						       hal_ind_msg->msg,
2568 						       hal_ind_msg->msg_len);
2569 			break;
2570 		case WCN36XX_HAL_SCAN_OFFLOAD_IND:
2571 			wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg,
2572 						hal_ind_msg->msg_len);
2573 			break;
2574 		default:
2575 			wcn36xx_err("SMD_EVENT (%d) not supported\n",
2576 				    msg_header->msg_type);
2577 		}
2578 
2579 		kfree(hal_ind_msg);
2580 	}
2581 }
2582 int wcn36xx_smd_open(struct wcn36xx *wcn)
2583 {
2584 	wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind");
2585 	if (!wcn->hal_ind_wq)
2586 		return -ENOMEM;
2587 
2588 	INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
2589 	INIT_LIST_HEAD(&wcn->hal_ind_queue);
2590 	spin_lock_init(&wcn->hal_ind_lock);
2591 
2592 	return 0;
2593 }
2594 
2595 void wcn36xx_smd_close(struct wcn36xx *wcn)
2596 {
2597 	struct wcn36xx_hal_ind_msg *msg, *tmp;
2598 
2599 	cancel_work_sync(&wcn->hal_ind_work);
2600 	destroy_workqueue(wcn->hal_ind_wq);
2601 
2602 	list_for_each_entry_safe(msg, tmp, &wcn->hal_ind_queue, list)
2603 		kfree(msg);
2604 }
2605