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