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