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