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