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