[go: nahoru, domu]

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