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/bitfield.h>
20#include <linux/etherdevice.h>
21#include <linux/firmware.h>
22#include <linux/bitops.h>
23#include <linux/rpmsg.h>
24#include "smd.h"
25#include "firmware.h"
26
27struct wcn36xx_cfg_val {
28	u32 cfg_id;
29	u32 value;
30};
31
32#define WCN36XX_CFG_VAL(id, val) \
33{ \
34	.cfg_id = WCN36XX_HAL_CFG_ ## id, \
35	.value = val \
36}
37
38static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = {
39	WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
40	WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
41	WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0),
42	WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785),
43	WCN36XX_CFG_VAL(CAL_PERIOD, 5),
44	WCN36XX_CFG_VAL(CAL_CONTROL, 1),
45	WCN36XX_CFG_VAL(PROXIMITY, 0),
46	WCN36XX_CFG_VAL(NETWORK_DENSITY, 3),
47	WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 6000),
48	WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64),
49	WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347),
50	WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 15),
51	WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 15),
52	WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000),
53	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5),
54	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10),
55	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15),
56	WCN36XX_CFG_VAL(FIXED_RATE, 0),
57	WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4),
58	WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 0),
59	WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 0),
60	WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5),
61	WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1),
62	WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5),
63	WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5),
64	WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40),
65	WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200),
66	WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1),
67	WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1),
68	WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20),
69	WCN36XX_CFG_VAL(STATS_PERIOD, 10),
70	WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000),
71	WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0),
72	WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128),
73	WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560),
74	WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
75	WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
76	WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
77	WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
78	WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 120000),
79	WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000),
80	WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
81	WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
82	WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 133), /* MCS 5 */
83	WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 1000),
84};
85
86static struct wcn36xx_cfg_val wcn3680_cfg_vals[] = {
87	WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
88	WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
89	WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0),
90	WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785),
91	WCN36XX_CFG_VAL(CAL_PERIOD, 5),
92	WCN36XX_CFG_VAL(CAL_CONTROL, 1),
93	WCN36XX_CFG_VAL(PROXIMITY, 0),
94	WCN36XX_CFG_VAL(NETWORK_DENSITY, 3),
95	WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 4096),
96	WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64),
97	WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347),
98	WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 15),
99	WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 15),
100	WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000),
101	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5),
102	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10),
103	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15),
104	WCN36XX_CFG_VAL(FIXED_RATE, 0),
105	WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4),
106	WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 0),
107	WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 0),
108	WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5),
109	WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1),
110	WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5),
111	WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_24GHZ, 1),
112	WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5),
113	WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40),
114	WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200),
115	WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1),
116	WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1),
117	WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20),
118	WCN36XX_CFG_VAL(STATS_PERIOD, 10),
119	WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000),
120	WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0),
121	WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128),
122	WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560),
123	WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
124	WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
125	WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
126	WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
127	WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 120000),
128	WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000),
129	WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
130	WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
131	WCN36XX_CFG_VAL(TDLS_PUAPSD_MASK, 0),
132	WCN36XX_CFG_VAL(TDLS_PUAPSD_BUFFER_STA_CAPABLE, 1),
133	WCN36XX_CFG_VAL(TDLS_PUAPSD_INACTIVITY_TIME, 0),
134	WCN36XX_CFG_VAL(TDLS_PUAPSD_RX_FRAME_THRESHOLD, 10),
135	WCN36XX_CFG_VAL(TDLS_OFF_CHANNEL_CAPABLE, 1),
136	WCN36XX_CFG_VAL(ENABLE_ADAPTIVE_RX_DRAIN, 1),
137	WCN36XX_CFG_VAL(FLEXCONNECT_POWER_FACTOR, 0),
138	WCN36XX_CFG_VAL(ANTENNA_DIVERSITY, 3),
139	WCN36XX_CFG_VAL(ATH_DISABLE, 0),
140	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_WLAN_LEN, 60000),
141	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_BT_LEN, 90000),
142	WCN36XX_CFG_VAL(BTC_SAP_STATIC_OPP_ACTIVE_WLAN_LEN, 30000),
143	WCN36XX_CFG_VAL(BTC_SAP_STATIC_OPP_ACTIVE_BT_LEN, 30000),
144	WCN36XX_CFG_VAL(ASD_PROBE_INTERVAL, 50),
145	WCN36XX_CFG_VAL(ASD_TRIGGER_THRESHOLD, -60),
146	WCN36XX_CFG_VAL(ASD_RTT_RSSI_HYST_THRESHOLD, 3),
147	WCN36XX_CFG_VAL(BTC_CTS2S_ON_STA_DURING_SCO, 0),
148	WCN36XX_CFG_VAL(RA_FILTER_ENABLE, 0),
149	WCN36XX_CFG_VAL(RA_RATE_LIMIT_INTERVAL, 60),
150	WCN36XX_CFG_VAL(BTC_FATAL_HID_NSNIFF_BLK, 2),
151	WCN36XX_CFG_VAL(BTC_CRITICAL_HID_NSNIFF_BLK, 1),
152	WCN36XX_CFG_VAL(BTC_DYN_A2DP_TX_QUEUE_THOLD, 0),
153	WCN36XX_CFG_VAL(BTC_DYN_OPP_TX_QUEUE_THOLD, 1),
154	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_SP, 10),
155	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_RX_CNT, 50),
156	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_TX_CNT, 50),
157	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_TX_CNT_MEAS_WINDOW, 500),
158	WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_RX_CNT_MEAS_WINDOW, 500),
159	WCN36XX_CFG_VAL(MAX_PSPOLL_IN_WMM_UAPSD_PS_MODE, 0),
160	WCN36XX_CFG_VAL(MAX_UAPSD_INACTIVITY_INTERVALS, 10),
161	WCN36XX_CFG_VAL(ENABLE_DYNAMIC_WMMPS, 1),
162	WCN36XX_CFG_VAL(BURST_MODE_BE_TXOP_VALUE, 0),
163	WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 136),
164	WCN36XX_CFG_VAL(BTC_FAST_WLAN_CONN_PREF, 1),
165	WCN36XX_CFG_VAL(ENABLE_RTSCTS_HTVHT, 0),
166	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_WLAN_LEN, 30000),
167	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_BT_LEN, 120000),
168	WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 1000),
169	WCN36XX_CFG_VAL(TOGGLE_ARP_BDRATES, 0),
170	WCN36XX_CFG_VAL(OPTIMIZE_CA_EVENT, 0),
171	WCN36XX_CFG_VAL(EXT_SCAN_CONC_MODE, 0),
172	WCN36XX_CFG_VAL(BAR_WAKEUP_HOST_DISABLE, 0),
173	WCN36XX_CFG_VAL(SAR_BOFFSET_CORRECTION_ENABLE, 0),
174	WCN36XX_CFG_VAL(BTC_DISABLE_WLAN_LINK_CRITICAL, 5),
175	WCN36XX_CFG_VAL(DISABLE_SCAN_DURING_SCO, 2),
176	WCN36XX_CFG_VAL(CONS_BCNMISS_COUNT, 0),
177	WCN36XX_CFG_VAL(UNITS_OF_BCN_WAIT_TIME, 0),
178	WCN36XX_CFG_VAL(TRIGGER_NULLFRAME_BEFORE_HB, 0),
179	WCN36XX_CFG_VAL(ENABLE_POWERSAVE_OFFLOAD, 0),
180};
181
182static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value)
183{
184	struct wcn36xx_hal_cfg *entry;
185	u32 *val;
186
187	if (*len + sizeof(*entry) + sizeof(u32) >= WCN36XX_HAL_BUF_SIZE) {
188		wcn36xx_err("Not enough room for TLV entry\n");
189		return -ENOMEM;
190	}
191
192	entry = (struct wcn36xx_hal_cfg *) (wcn->hal_buf + *len);
193	entry->id = id;
194	entry->len = sizeof(u32);
195	entry->pad_bytes = 0;
196	entry->reserve = 0;
197
198	val = (u32 *) (entry + 1);
199	*val = value;
200
201	*len += sizeof(*entry) + sizeof(u32);
202
203	return 0;
204}
205
206static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn,
207		struct ieee80211_sta *sta,
208		struct wcn36xx_hal_config_bss_params *bss_params)
209{
210	if (NL80211_BAND_5GHZ == WCN36XX_BAND(wcn))
211		bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE;
212	else if (sta && sta->deflink.ht_cap.ht_supported)
213		bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE;
214	else if (sta && (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0x7f))
215		bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE;
216	else
217		bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE;
218}
219
220static inline u8 is_cap_supported(unsigned long caps, unsigned long flag)
221{
222	return caps & flag ? 1 : 0;
223}
224
225static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif,
226		struct ieee80211_sta *sta,
227		struct wcn36xx_hal_config_bss_params *bss_params)
228{
229	if (sta && sta->deflink.ht_cap.ht_supported) {
230		unsigned long caps = sta->deflink.ht_cap.cap;
231
232		bss_params->ht = sta->deflink.ht_cap.ht_supported;
233		bss_params->tx_channel_width_set = is_cap_supported(caps,
234			IEEE80211_HT_CAP_SUP_WIDTH_20_40);
235		bss_params->lsig_tx_op_protection_full_support =
236			is_cap_supported(caps,
237					 IEEE80211_HT_CAP_LSIG_TXOP_PROT);
238
239		bss_params->ht_oper_mode = vif->bss_conf.ht_operation_mode;
240		bss_params->lln_non_gf_coexist =
241			!!(vif->bss_conf.ht_operation_mode &
242			   IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
243		/* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */
244		bss_params->dual_cts_protection = 0;
245		/* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */
246		bss_params->ht20_coexist = 0;
247	}
248}
249
250static void
251wcn36xx_smd_set_bss_vht_params(struct ieee80211_vif *vif,
252			       struct ieee80211_sta *sta,
253			       struct wcn36xx_hal_config_bss_params_v1 *bss)
254{
255	if (sta && sta->deflink.vht_cap.vht_supported)
256		bss->vht_capable = 1;
257}
258
259static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta,
260		struct wcn36xx_hal_config_sta_params *sta_params)
261{
262	if (sta->deflink.ht_cap.ht_supported) {
263		unsigned long caps = sta->deflink.ht_cap.cap;
264
265		sta_params->ht_capable = sta->deflink.ht_cap.ht_supported;
266		sta_params->tx_channel_width_set = is_cap_supported(caps,
267			IEEE80211_HT_CAP_SUP_WIDTH_20_40);
268		sta_params->lsig_txop_protection = is_cap_supported(caps,
269			IEEE80211_HT_CAP_LSIG_TXOP_PROT);
270
271		sta_params->max_ampdu_size = sta->deflink.ht_cap.ampdu_factor;
272		sta_params->max_ampdu_density = sta->deflink.ht_cap.ampdu_density;
273		/* max_amsdu_size: 1 : 3839 bytes, 0 : 7935 bytes (max) */
274		sta_params->max_amsdu_size = !is_cap_supported(caps,
275			IEEE80211_HT_CAP_MAX_AMSDU);
276		sta_params->sgi_20Mhz = is_cap_supported(caps,
277			IEEE80211_HT_CAP_SGI_20);
278		sta_params->sgi_40mhz =	is_cap_supported(caps,
279			IEEE80211_HT_CAP_SGI_40);
280		sta_params->green_field_capable = is_cap_supported(caps,
281			IEEE80211_HT_CAP_GRN_FLD);
282		sta_params->delayed_ba_support = is_cap_supported(caps,
283			IEEE80211_HT_CAP_DELAY_BA);
284		sta_params->dsss_cck_mode_40mhz = is_cap_supported(caps,
285			IEEE80211_HT_CAP_DSSSCCK40);
286	}
287}
288
289static void wcn36xx_smd_set_sta_vht_params(struct wcn36xx *wcn,
290		struct ieee80211_sta *sta,
291		struct wcn36xx_hal_config_sta_params_v1 *sta_params)
292{
293	if (sta->deflink.vht_cap.vht_supported) {
294		unsigned long caps = sta->deflink.vht_cap.cap;
295
296		sta_params->vht_capable = sta->deflink.vht_cap.vht_supported;
297		sta_params->vht_ldpc_enabled =
298			is_cap_supported(caps, IEEE80211_VHT_CAP_RXLDPC);
299		if (wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, MU_MIMO)) {
300			sta_params->vht_tx_mu_beamformee_capable =
301				is_cap_supported(caps, IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
302			if (sta_params->vht_tx_mu_beamformee_capable)
303			       sta_params->vht_tx_bf_enabled = 1;
304		} else {
305			sta_params->vht_tx_mu_beamformee_capable = 0;
306		}
307		sta_params->vht_tx_channel_width_set = 0;
308	}
309}
310
311static void wcn36xx_smd_set_sta_ht_ldpc_params(struct ieee80211_sta *sta,
312		struct wcn36xx_hal_config_sta_params_v1 *sta_params)
313{
314	if (sta->deflink.ht_cap.ht_supported) {
315		sta_params->ht_ldpc_enabled =
316			is_cap_supported(sta->deflink.ht_cap.cap,
317					 IEEE80211_HT_CAP_LDPC_CODING);
318	}
319}
320
321static void wcn36xx_smd_set_sta_default_ht_params(
322		struct wcn36xx_hal_config_sta_params *sta_params)
323{
324	sta_params->ht_capable = 1;
325	sta_params->tx_channel_width_set = 1;
326	sta_params->lsig_txop_protection = 1;
327	sta_params->max_ampdu_size = 3;
328	sta_params->max_ampdu_density = 5;
329	sta_params->max_amsdu_size = 0;
330	sta_params->sgi_20Mhz = 1;
331	sta_params->sgi_40mhz = 1;
332	sta_params->green_field_capable = 1;
333	sta_params->delayed_ba_support = 0;
334	sta_params->dsss_cck_mode_40mhz = 1;
335}
336
337static void wcn36xx_smd_set_sta_default_vht_params(struct wcn36xx *wcn,
338		struct wcn36xx_hal_config_sta_params_v1 *sta_params)
339{
340	if (wcn->rf_id == RF_IRIS_WCN3680) {
341		sta_params->vht_capable = 1;
342		sta_params->vht_tx_mu_beamformee_capable = 1;
343	} else {
344		sta_params->vht_capable = 0;
345		sta_params->vht_tx_mu_beamformee_capable = 0;
346	}
347
348	sta_params->vht_ldpc_enabled = 0;
349	sta_params->vht_tx_channel_width_set = 0;
350	sta_params->vht_tx_bf_enabled = 0;
351}
352
353static void wcn36xx_smd_set_sta_default_ht_ldpc_params(struct wcn36xx *wcn,
354		struct wcn36xx_hal_config_sta_params_v1 *sta_params)
355{
356	if (wcn->rf_id == RF_IRIS_WCN3680)
357		sta_params->ht_ldpc_enabled = 1;
358	else
359		sta_params->ht_ldpc_enabled = 0;
360}
361
362static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
363		struct ieee80211_vif *vif,
364		struct ieee80211_sta *sta,
365		struct wcn36xx_hal_config_sta_params *sta_params)
366{
367	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
368	struct wcn36xx_sta *sta_priv = NULL;
369	if (vif->type == NL80211_IFTYPE_ADHOC ||
370	    vif->type == NL80211_IFTYPE_AP ||
371	    vif->type == NL80211_IFTYPE_MESH_POINT) {
372		sta_params->type = 1;
373		sta_params->sta_index = WCN36XX_HAL_STA_INVALID_IDX;
374	} else {
375		sta_params->type = 0;
376		sta_params->sta_index = vif_priv->self_sta_index;
377	}
378
379	sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
380
381	/*
382	 * In STA mode ieee80211_sta contains bssid and ieee80211_vif
383	 * contains our mac address. In  AP mode we are bssid so vif
384	 * contains bssid and ieee80211_sta contains mac.
385	 */
386	if (NL80211_IFTYPE_STATION == vif->type)
387		memcpy(&sta_params->mac, vif->addr, ETH_ALEN);
388	else
389		memcpy(&sta_params->bssid, vif->addr, ETH_ALEN);
390
391	sta_params->encrypt_type = vif_priv->encrypt_type;
392	sta_params->short_preamble_supported = true;
393
394	sta_params->rifs_mode = 0;
395	sta_params->rmf = 0;
396	sta_params->action = 0;
397	sta_params->uapsd = 0;
398	sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC;
399	sta_params->max_ampdu_duration = 0;
400	sta_params->bssid_index = vif_priv->bss_index;
401	sta_params->p2p = 0;
402
403	if (sta) {
404		sta_priv = wcn36xx_sta_to_priv(sta);
405		if (NL80211_IFTYPE_STATION == vif->type)
406			memcpy(&sta_params->bssid, sta->addr, ETH_ALEN);
407		else
408			memcpy(&sta_params->mac, sta->addr, ETH_ALEN);
409		sta_params->wmm_enabled = sta->wme;
410		sta_params->max_sp_len = sta->max_sp;
411		sta_params->aid = sta_priv->aid;
412		wcn36xx_smd_set_sta_ht_params(sta, sta_params);
413		memcpy(&sta_params->supported_rates, &sta_priv->supported_rates,
414			sizeof(struct wcn36xx_hal_supported_rates));
415	} else {
416		wcn36xx_set_default_rates((struct wcn36xx_hal_supported_rates *)
417					  &sta_params->supported_rates);
418		wcn36xx_smd_set_sta_default_ht_params(sta_params);
419	}
420}
421
422static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
423{
424	int ret;
425	unsigned long start;
426	struct wcn36xx_hal_msg_header *hdr =
427		(struct wcn36xx_hal_msg_header *)wcn->hal_buf;
428	u16 req_type = hdr->msg_type;
429
430	wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len);
431
432	init_completion(&wcn->hal_rsp_compl);
433	start = jiffies;
434	ret = rpmsg_send(wcn->smd_channel, wcn->hal_buf, len);
435	if (ret) {
436		wcn36xx_err("HAL TX failed for req %d\n", req_type);
437		goto out;
438	}
439	if (wait_for_completion_timeout(&wcn->hal_rsp_compl,
440		msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) {
441		wcn36xx_err("Timeout! No SMD response to req %d in %dms\n",
442			    req_type, HAL_MSG_TIMEOUT);
443		ret = -ETIME;
444		goto out;
445	}
446	wcn36xx_dbg(WCN36XX_DBG_SMD,
447		    "SMD command (req %d, rsp %d) completed in %dms\n",
448		    req_type, hdr->msg_type,
449		    jiffies_to_msecs(jiffies - start));
450out:
451	return ret;
452}
453
454#define __INIT_HAL_MSG(msg_body, type, version) \
455	do {								\
456		memset(&(msg_body), 0, sizeof(msg_body));		\
457		(msg_body).header.msg_type = type;			\
458		(msg_body).header.msg_version = version;		\
459		(msg_body).header.len = sizeof(msg_body);		\
460	} while (0)							\
461
462#define INIT_HAL_MSG(msg_body, type)	\
463	__INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION0)
464
465#define INIT_HAL_MSG_V1(msg_body, type) \
466	__INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION1)
467
468#define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \
469	do { \
470		memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \
471		p_msg_body->header.msg_type = WCN36XX_HAL_PROCESS_PTT_REQ; \
472		p_msg_body->header.msg_version = WCN36XX_HAL_MSG_VERSION0; \
473		p_msg_body->header.len = sizeof(*p_msg_body) + ppt_msg_len; \
474	} while (0)
475
476#define PREPARE_HAL_BUF(send_buf, msg_body) \
477	do {							\
478		memcpy_and_pad(send_buf, msg_body.header.len,	\
479			       &msg_body, sizeof(msg_body), 0);	\
480	} while (0)						\
481
482#define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \
483	do {							\
484		memcpy(send_buf, p_msg_body, p_msg_body->header.len); \
485	} while (0)
486
487static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
488{
489	struct wcn36xx_fw_msg_status_rsp *rsp;
490
491	if (len < sizeof(struct wcn36xx_hal_msg_header) +
492	    sizeof(struct wcn36xx_fw_msg_status_rsp))
493		return -EIO;
494
495	rsp = (struct wcn36xx_fw_msg_status_rsp *)
496		(buf + sizeof(struct wcn36xx_hal_msg_header));
497
498	if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
499		return rsp->status;
500
501	return 0;
502}
503
504int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
505{
506	struct nv_data *nv_d;
507	struct wcn36xx_hal_nv_img_download_req_msg msg_body;
508	int fw_bytes_left;
509	int ret;
510	u16 fm_offset = 0;
511
512	if (!wcn->nv) {
513		ret = request_firmware(&wcn->nv, wcn->nv_file, wcn->dev);
514		if (ret) {
515			wcn36xx_err("Failed to load nv file %s: %d\n",
516				    wcn->nv_file, ret);
517			goto out;
518		}
519	}
520
521	nv_d = (struct nv_data *)wcn->nv->data;
522	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ);
523
524	msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE;
525
526	msg_body.frag_number = 0;
527	/* hal_buf must be protected with  mutex */
528	mutex_lock(&wcn->hal_mutex);
529
530	do {
531		fw_bytes_left = wcn->nv->size - fm_offset - 4;
532		if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) {
533			msg_body.last_fragment = 0;
534			msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE;
535		} else {
536			msg_body.last_fragment = 1;
537			msg_body.nv_img_buffer_size = fw_bytes_left;
538
539			/* Do not forget update general message len */
540			msg_body.header.len = sizeof(msg_body) + fw_bytes_left;
541
542		}
543
544		/* Add load NV request message header */
545		memcpy(wcn->hal_buf, &msg_body,	sizeof(msg_body));
546
547		/* Add NV body itself */
548		memcpy(wcn->hal_buf + sizeof(msg_body),
549		       &nv_d->table + fm_offset,
550		       msg_body.nv_img_buffer_size);
551
552		ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
553		if (ret)
554			goto out_unlock;
555		ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf,
556						   wcn->hal_rsp_len);
557		if (ret) {
558			wcn36xx_err("hal_load_nv response failed err=%d\n",
559				    ret);
560			goto out_unlock;
561		}
562		msg_body.frag_number++;
563		fm_offset += WCN36XX_NV_FRAGMENT_SIZE;
564
565	} while (msg_body.last_fragment != 1);
566
567out_unlock:
568	mutex_unlock(&wcn->hal_mutex);
569out:	return ret;
570}
571
572static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
573{
574	struct wcn36xx_hal_mac_start_rsp_msg *rsp;
575
576	if (len < sizeof(*rsp))
577		return -EIO;
578
579	rsp = buf;
580
581	if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->start_rsp_params.status)
582		return -EIO;
583
584	memcpy(wcn->crm_version, rsp->start_rsp_params.crm_version,
585	       WCN36XX_HAL_VERSION_LENGTH);
586	memcpy(wcn->wlan_version, rsp->start_rsp_params.wlan_version,
587	       WCN36XX_HAL_VERSION_LENGTH);
588
589	/* null terminate the strings, just in case */
590	wcn->crm_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
591	wcn->wlan_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
592
593	wcn->fw_revision = rsp->start_rsp_params.version.revision;
594	wcn->fw_version = rsp->start_rsp_params.version.version;
595	wcn->fw_minor = rsp->start_rsp_params.version.minor;
596	wcn->fw_major = rsp->start_rsp_params.version.major;
597
598	if (wcn->first_boot) {
599		wcn->first_boot = false;
600		wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n",
601			     wcn->wlan_version, wcn->crm_version);
602
603		wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n",
604			     wcn->fw_major, wcn->fw_minor,
605			     wcn->fw_version, wcn->fw_revision,
606			     rsp->start_rsp_params.stations,
607			     rsp->start_rsp_params.bssids);
608	}
609	return 0;
610}
611
612int wcn36xx_smd_start(struct wcn36xx *wcn)
613{
614	struct wcn36xx_hal_mac_start_req_msg msg_body, *body;
615	int ret;
616	int i;
617	size_t len;
618	int cfg_elements;
619	static struct wcn36xx_cfg_val *cfg_vals;
620
621	mutex_lock(&wcn->hal_mutex);
622	INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ);
623
624	msg_body.params.type = DRIVER_TYPE_PRODUCTION;
625	msg_body.params.len = 0;
626
627	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
628
629	body = (struct wcn36xx_hal_mac_start_req_msg *)wcn->hal_buf;
630	len = body->header.len;
631
632	if (wcn->rf_id == RF_IRIS_WCN3680) {
633		cfg_vals = wcn3680_cfg_vals;
634		cfg_elements = ARRAY_SIZE(wcn3680_cfg_vals);
635	} else {
636		cfg_vals = wcn36xx_cfg_vals;
637		cfg_elements = ARRAY_SIZE(wcn36xx_cfg_vals);
638	}
639
640	for (i = 0; i < cfg_elements; i++) {
641		ret = put_cfg_tlv_u32(wcn, &len, cfg_vals[i].cfg_id,
642				      cfg_vals[i].value);
643		if (ret)
644			goto out;
645	}
646	body->header.len = len;
647	body->params.len = len - sizeof(*body);
648
649	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n",
650		    msg_body.params.type);
651
652	ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
653	if (ret) {
654		wcn36xx_err("Sending hal_start failed\n");
655		goto out;
656	}
657
658	ret = wcn36xx_smd_start_rsp(wcn, wcn->hal_buf, wcn->hal_rsp_len);
659	if (ret) {
660		wcn36xx_err("hal_start response failed err=%d\n", ret);
661		goto out;
662	}
663
664out:
665	mutex_unlock(&wcn->hal_mutex);
666	return ret;
667}
668
669int wcn36xx_smd_stop(struct wcn36xx *wcn)
670{
671	struct wcn36xx_hal_mac_stop_req_msg msg_body;
672	int ret;
673
674	mutex_lock(&wcn->hal_mutex);
675	INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ);
676
677	msg_body.stop_req_params.reason = HAL_STOP_TYPE_RF_KILL;
678
679	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
680
681	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
682	if (ret) {
683		wcn36xx_err("Sending hal_stop failed\n");
684		goto out;
685	}
686	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
687	if (ret) {
688		wcn36xx_err("hal_stop response failed err=%d\n", ret);
689		goto out;
690	}
691out:
692	mutex_unlock(&wcn->hal_mutex);
693	return ret;
694}
695
696int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode,
697			  struct ieee80211_vif *vif)
698{
699	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
700	struct wcn36xx_hal_init_scan_req_msg msg_body;
701	int ret;
702
703	mutex_lock(&wcn->hal_mutex);
704	INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ);
705
706	msg_body.mode = mode;
707	if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX) {
708		/* Notify BSSID with null DATA packet */
709		msg_body.frame_type = 2;
710		msg_body.notify = 1;
711		msg_body.scan_entry.bss_index[0] = vif_priv->bss_index;
712		msg_body.scan_entry.active_bss_count = 1;
713	}
714
715	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
716
717	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d\n", msg_body.mode);
718
719	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
720	if (ret) {
721		wcn36xx_err("Sending hal_init_scan failed\n");
722		goto out;
723	}
724	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
725	if (ret) {
726		wcn36xx_err("hal_init_scan response failed err=%d\n", ret);
727		goto out;
728	}
729	wcn->sw_scan_init = true;
730out:
731	mutex_unlock(&wcn->hal_mutex);
732	return ret;
733}
734
735int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel)
736{
737	struct wcn36xx_hal_start_scan_req_msg msg_body;
738	int ret;
739
740	mutex_lock(&wcn->hal_mutex);
741	INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ);
742
743	msg_body.scan_channel = scan_channel;
744
745	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
746
747	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start scan channel %d\n",
748		    msg_body.scan_channel);
749
750	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
751	if (ret) {
752		wcn36xx_err("Sending hal_start_scan failed\n");
753		goto out;
754	}
755	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
756	if (ret) {
757		wcn36xx_err("hal_start_scan response failed err=%d\n", ret);
758		goto out;
759	}
760	wcn->sw_scan_channel = scan_channel;
761out:
762	mutex_unlock(&wcn->hal_mutex);
763	return ret;
764}
765
766int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel)
767{
768	struct wcn36xx_hal_end_scan_req_msg msg_body;
769	int ret;
770
771	mutex_lock(&wcn->hal_mutex);
772	INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ);
773
774	msg_body.scan_channel = scan_channel;
775
776	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
777
778	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d\n",
779		    msg_body.scan_channel);
780
781	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
782	if (ret) {
783		wcn36xx_err("Sending hal_end_scan failed\n");
784		goto out;
785	}
786	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
787	if (ret) {
788		wcn36xx_err("hal_end_scan response failed err=%d\n", ret);
789		goto out;
790	}
791	wcn->sw_scan_channel = 0;
792out:
793	mutex_unlock(&wcn->hal_mutex);
794	return ret;
795}
796
797int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
798			    enum wcn36xx_hal_sys_mode mode,
799			    struct ieee80211_vif *vif)
800{
801	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
802	struct wcn36xx_hal_finish_scan_req_msg msg_body;
803	int ret;
804
805	mutex_lock(&wcn->hal_mutex);
806	INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ);
807
808	msg_body.mode = mode;
809	msg_body.oper_channel = WCN36XX_HW_CHANNEL(wcn);
810	if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX) {
811		/* Notify BSSID with null data packet */
812		msg_body.notify = 1;
813		msg_body.frame_type = 2;
814		msg_body.scan_entry.bss_index[0] = vif_priv->bss_index;
815		msg_body.scan_entry.active_bss_count = 1;
816	}
817
818	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
819
820	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal finish scan mode %d\n",
821		    msg_body.mode);
822
823	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
824	if (ret) {
825		wcn36xx_err("Sending hal_finish_scan failed\n");
826		goto out;
827	}
828	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
829	if (ret) {
830		wcn36xx_err("hal_finish_scan response failed err=%d\n", ret);
831		goto out;
832	}
833	wcn->sw_scan_init = false;
834out:
835	mutex_unlock(&wcn->hal_mutex);
836	return ret;
837}
838
839int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif,
840			      struct cfg80211_scan_request *req)
841{
842	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
843	struct wcn36xx_hal_start_scan_offload_req_msg *msg_body;
844	int ret, i;
845
846	if (req->ie_len > WCN36XX_MAX_SCAN_IE_LEN)
847		return -EINVAL;
848
849	mutex_lock(&wcn->hal_mutex);
850	msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
851	if (!msg_body) {
852		ret = -ENOMEM;
853		goto out;
854	}
855
856	INIT_HAL_MSG((*msg_body), WCN36XX_HAL_START_SCAN_OFFLOAD_REQ);
857
858	msg_body->scan_type = WCN36XX_HAL_SCAN_TYPE_ACTIVE;
859	msg_body->min_ch_time = 30;
860	msg_body->max_ch_time = 100;
861	msg_body->scan_hidden = 1;
862	memcpy(msg_body->mac, vif->addr, ETH_ALEN);
863	msg_body->bss_type = vif_priv->bss_type;
864	msg_body->p2p_search = vif->p2p;
865
866	msg_body->num_ssid = min_t(u8, req->n_ssids, ARRAY_SIZE(msg_body->ssids));
867	for (i = 0; i < msg_body->num_ssid; i++) {
868		msg_body->ssids[i].length = min_t(u8, req->ssids[i].ssid_len,
869						sizeof(msg_body->ssids[i].ssid));
870		memcpy(msg_body->ssids[i].ssid, req->ssids[i].ssid,
871		       msg_body->ssids[i].length);
872	}
873
874	msg_body->num_channel = min_t(u8, req->n_channels,
875				     sizeof(msg_body->channels));
876	for (i = 0; i < msg_body->num_channel; i++) {
877		msg_body->channels[i] =
878			HW_VALUE_CHANNEL(req->channels[i]->hw_value);
879	}
880
881	msg_body->header.len -= WCN36XX_MAX_SCAN_IE_LEN;
882
883	if (req->ie_len > 0) {
884		msg_body->ie_len = req->ie_len;
885		msg_body->header.len += req->ie_len;
886		memcpy(msg_body->ie, req->ie, req->ie_len);
887	}
888
889	PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
890
891	wcn36xx_dbg(WCN36XX_DBG_HAL,
892		    "hal start hw-scan (channels: %u; ssids: %u; p2p: %s)\n",
893		    msg_body->num_channel, msg_body->num_ssid,
894		    msg_body->p2p_search ? "yes" : "no");
895
896	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
897	if (ret) {
898		wcn36xx_err("Sending hal_start_scan_offload failed\n");
899		goto out;
900	}
901	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
902	if (ret) {
903		wcn36xx_err("hal_start_scan_offload response failed err=%d\n",
904			    ret);
905		goto out;
906	}
907out:
908	kfree(msg_body);
909	mutex_unlock(&wcn->hal_mutex);
910	return ret;
911}
912
913int wcn36xx_smd_stop_hw_scan(struct wcn36xx *wcn)
914{
915	struct wcn36xx_hal_stop_scan_offload_req_msg msg_body;
916	int ret;
917
918	mutex_lock(&wcn->hal_mutex);
919	INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_SCAN_OFFLOAD_REQ);
920	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
921
922	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal stop hw-scan\n");
923
924	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
925	if (ret) {
926		wcn36xx_err("Sending hal_stop_scan_offload failed\n");
927		goto out;
928	}
929	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
930	if (ret) {
931		wcn36xx_err("hal_stop_scan_offload response failed err=%d\n",
932			    ret);
933		goto out;
934	}
935out:
936	mutex_unlock(&wcn->hal_mutex);
937	return ret;
938}
939
940int wcn36xx_smd_update_channel_list(struct wcn36xx *wcn, struct cfg80211_scan_request *req)
941{
942	struct wcn36xx_hal_update_channel_list_req_msg *msg_body;
943	int ret, i;
944
945	msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
946	if (!msg_body)
947		return -ENOMEM;
948
949	INIT_HAL_MSG((*msg_body), WCN36XX_HAL_UPDATE_CHANNEL_LIST_REQ);
950
951	msg_body->num_channel = min_t(u8, req->n_channels, ARRAY_SIZE(msg_body->channels));
952	for (i = 0; i < msg_body->num_channel; i++) {
953		struct wcn36xx_hal_channel_param *param = &msg_body->channels[i];
954		u32 min_power = WCN36XX_HAL_DEFAULT_MIN_POWER;
955		u32 ant_gain = WCN36XX_HAL_DEFAULT_ANT_GAIN;
956
957		param->mhz = req->channels[i]->center_freq;
958		param->band_center_freq1 = req->channels[i]->center_freq;
959		param->band_center_freq2 = 0;
960
961		if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR)
962			param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_PASSIVE;
963
964		if (req->channels[i]->flags & IEEE80211_CHAN_RADAR)
965			param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_DFS;
966
967		if (req->channels[i]->band == NL80211_BAND_5GHZ) {
968			param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_HT;
969			param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_VHT;
970			param->channel_info |= WCN36XX_HAL_CHAN_INFO_PHY_11A;
971		} else {
972			param->channel_info |= WCN36XX_HAL_CHAN_INFO_PHY_11BG;
973		}
974
975		if (min_power > req->channels[i]->max_power)
976			min_power = req->channels[i]->max_power;
977
978		if (req->channels[i]->max_antenna_gain)
979			ant_gain = req->channels[i]->max_antenna_gain;
980
981		u32p_replace_bits(&param->reg_info_1, min_power,
982				  WCN36XX_HAL_CHAN_REG1_MIN_PWR_MASK);
983		u32p_replace_bits(&param->reg_info_1, req->channels[i]->max_power,
984				  WCN36XX_HAL_CHAN_REG1_MAX_PWR_MASK);
985		u32p_replace_bits(&param->reg_info_1, req->channels[i]->max_reg_power,
986				  WCN36XX_HAL_CHAN_REG1_REG_PWR_MASK);
987		u32p_replace_bits(&param->reg_info_1, 0,
988				  WCN36XX_HAL_CHAN_REG1_CLASS_ID_MASK);
989		u32p_replace_bits(&param->reg_info_2, ant_gain,
990				  WCN36XX_HAL_CHAN_REG2_ANT_GAIN_MASK);
991
992		wcn36xx_dbg(WCN36XX_DBG_HAL,
993			    "%s: freq=%u, channel_info=%08x, reg_info1=%08x, reg_info2=%08x\n",
994			    __func__, param->mhz, param->channel_info, param->reg_info_1,
995			    param->reg_info_2);
996	}
997
998	mutex_lock(&wcn->hal_mutex);
999
1000	PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
1001
1002	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
1003	if (ret) {
1004		wcn36xx_err("Sending hal_update_channel_list failed\n");
1005		goto out;
1006	}
1007
1008	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1009	if (ret) {
1010		wcn36xx_err("hal_update_channel_list response failed err=%d\n", ret);
1011		goto out;
1012	}
1013
1014out:
1015	kfree(msg_body);
1016	mutex_unlock(&wcn->hal_mutex);
1017	return ret;
1018}
1019
1020static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len)
1021{
1022	struct wcn36xx_hal_switch_channel_rsp_msg *rsp;
1023	int ret;
1024
1025	ret = wcn36xx_smd_rsp_status_check(buf, len);
1026	if (ret)
1027		return ret;
1028	rsp = buf;
1029	wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d\n",
1030		    rsp->channel_number, rsp->status);
1031	return ret;
1032}
1033
1034int wcn36xx_smd_switch_channel(struct wcn36xx *wcn,
1035			       struct ieee80211_vif *vif, int ch)
1036{
1037	struct wcn36xx_hal_switch_channel_req_msg msg_body;
1038	int ret;
1039
1040	mutex_lock(&wcn->hal_mutex);
1041	INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ);
1042
1043	msg_body.channel_number = (u8)ch;
1044	msg_body.tx_mgmt_power = 0xbf;
1045	msg_body.max_tx_power = 0xbf;
1046	memcpy(msg_body.self_sta_mac_addr, vif->addr, ETH_ALEN);
1047
1048	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1049
1050	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1051	if (ret) {
1052		wcn36xx_err("Sending hal_switch_channel failed\n");
1053		goto out;
1054	}
1055	ret = wcn36xx_smd_switch_channel_rsp(wcn->hal_buf, wcn->hal_rsp_len);
1056	if (ret) {
1057		wcn36xx_err("hal_switch_channel response failed err=%d\n", ret);
1058		goto out;
1059	}
1060out:
1061	mutex_unlock(&wcn->hal_mutex);
1062	return ret;
1063}
1064
1065static int wcn36xx_smd_process_ptt_msg_rsp(void *buf, size_t len,
1066					   void **p_ptt_rsp_msg)
1067{
1068	struct wcn36xx_hal_process_ptt_msg_rsp_msg *rsp;
1069	int ret;
1070
1071	ret = wcn36xx_smd_rsp_status_check(buf, len);
1072	if (ret)
1073		return ret;
1074
1075	rsp = buf;
1076
1077	wcn36xx_dbg(WCN36XX_DBG_HAL, "process ptt msg responded with length %d\n",
1078		    rsp->header.len);
1079	wcn36xx_dbg_dump(WCN36XX_DBG_HAL_DUMP, "HAL_PTT_MSG_RSP:", rsp->ptt_msg,
1080			 rsp->header.len - sizeof(rsp->ptt_msg_resp_status));
1081
1082	if (rsp->header.len > 0) {
1083		*p_ptt_rsp_msg = kmemdup(rsp->ptt_msg, rsp->header.len,
1084					 GFP_ATOMIC);
1085		if (!*p_ptt_rsp_msg)
1086			return -ENOMEM;
1087	}
1088	return ret;
1089}
1090
1091int wcn36xx_smd_process_ptt_msg(struct wcn36xx *wcn,
1092				struct ieee80211_vif *vif, void *ptt_msg, size_t len,
1093		void **ptt_rsp_msg)
1094{
1095	struct wcn36xx_hal_process_ptt_msg_req_msg *p_msg_body;
1096	int ret;
1097
1098	mutex_lock(&wcn->hal_mutex);
1099	p_msg_body = kmalloc(
1100		sizeof(struct wcn36xx_hal_process_ptt_msg_req_msg) + len,
1101		GFP_ATOMIC);
1102	if (!p_msg_body) {
1103		ret = -ENOMEM;
1104		goto out_nomem;
1105	}
1106	INIT_HAL_PTT_MSG(p_msg_body, len);
1107
1108	memcpy(&p_msg_body->ptt_msg, ptt_msg, len);
1109
1110	PREPARE_HAL_PTT_MSG_BUF(wcn->hal_buf, p_msg_body);
1111
1112	ret = wcn36xx_smd_send_and_wait(wcn, p_msg_body->header.len);
1113	if (ret) {
1114		wcn36xx_err("Sending hal_process_ptt_msg failed\n");
1115		goto out;
1116	}
1117	ret = wcn36xx_smd_process_ptt_msg_rsp(wcn->hal_buf, wcn->hal_rsp_len,
1118					      ptt_rsp_msg);
1119	if (ret) {
1120		wcn36xx_err("process_ptt_msg response failed err=%d\n", ret);
1121		goto out;
1122	}
1123out:
1124	kfree(p_msg_body);
1125out_nomem:
1126	mutex_unlock(&wcn->hal_mutex);
1127	return ret;
1128}
1129
1130static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len)
1131{
1132	struct wcn36xx_hal_update_scan_params_resp *rsp;
1133
1134	rsp = buf;
1135
1136	/* Remove the PNO version bit */
1137	rsp->status &= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK));
1138
1139	if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) {
1140		wcn36xx_warn("error response from update scan\n");
1141		return rsp->status;
1142	}
1143
1144	return 0;
1145}
1146
1147int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn,
1148				   u8 *channels, size_t channel_count)
1149{
1150	struct wcn36xx_hal_update_scan_params_req_ex msg_body;
1151	int ret;
1152
1153	mutex_lock(&wcn->hal_mutex);
1154	INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ);
1155
1156	msg_body.dot11d_enabled	= false;
1157	msg_body.dot11d_resolved = true;
1158
1159	msg_body.channel_count = channel_count;
1160	memcpy(msg_body.channels, channels, channel_count);
1161	msg_body.active_min_ch_time = 60;
1162	msg_body.active_max_ch_time = 120;
1163	msg_body.passive_min_ch_time = 60;
1164	msg_body.passive_max_ch_time = 110;
1165	msg_body.state = PHY_SINGLE_CHANNEL_CENTERED;
1166
1167	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1168
1169	wcn36xx_dbg(WCN36XX_DBG_HAL,
1170		    "hal update scan params channel_count %d\n",
1171		    msg_body.channel_count);
1172
1173	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1174	if (ret) {
1175		wcn36xx_err("Sending hal_update_scan_params failed\n");
1176		goto out;
1177	}
1178	ret = wcn36xx_smd_update_scan_params_rsp(wcn->hal_buf,
1179						 wcn->hal_rsp_len);
1180	if (ret) {
1181		wcn36xx_err("hal_update_scan_params response failed err=%d\n",
1182			    ret);
1183		goto out;
1184	}
1185out:
1186	mutex_unlock(&wcn->hal_mutex);
1187	return ret;
1188}
1189
1190static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
1191					struct ieee80211_vif *vif,
1192					void *buf,
1193					size_t len)
1194{
1195	struct wcn36xx_hal_add_sta_self_rsp_msg *rsp;
1196	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1197
1198	if (len < sizeof(*rsp))
1199		return -EINVAL;
1200
1201	rsp = buf;
1202
1203	if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1204		wcn36xx_warn("hal add sta self failure: %d\n",
1205			     rsp->status);
1206		return rsp->status;
1207	}
1208
1209	wcn36xx_dbg(WCN36XX_DBG_HAL,
1210		    "hal add sta self status %d self_sta_index %d dpu_index %d\n",
1211		    rsp->status, rsp->self_sta_index, rsp->dpu_index);
1212
1213	vif_priv->self_sta_index = rsp->self_sta_index;
1214	vif_priv->self_dpu_desc_index = rsp->dpu_index;
1215
1216	return 0;
1217}
1218
1219int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1220{
1221	struct wcn36xx_hal_add_sta_self_req msg_body;
1222	int ret;
1223
1224	mutex_lock(&wcn->hal_mutex);
1225	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ);
1226
1227	memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN);
1228
1229	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1230
1231	wcn36xx_dbg(WCN36XX_DBG_HAL,
1232		    "hal add sta self self_addr %pM status %d\n",
1233		    msg_body.self_addr, msg_body.status);
1234
1235	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1236	if (ret) {
1237		wcn36xx_err("Sending hal_add_sta_self failed\n");
1238		goto out;
1239	}
1240	ret = wcn36xx_smd_add_sta_self_rsp(wcn,
1241					   vif,
1242					   wcn->hal_buf,
1243					   wcn->hal_rsp_len);
1244	if (ret) {
1245		wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret);
1246		goto out;
1247	}
1248out:
1249	mutex_unlock(&wcn->hal_mutex);
1250	return ret;
1251}
1252
1253int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr)
1254{
1255	struct wcn36xx_hal_del_sta_self_req_msg msg_body;
1256	int ret;
1257
1258	mutex_lock(&wcn->hal_mutex);
1259	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ);
1260
1261	memcpy(&msg_body.self_addr, addr, ETH_ALEN);
1262
1263	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1264
1265	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1266	if (ret) {
1267		wcn36xx_err("Sending hal_delete_sta_self failed\n");
1268		goto out;
1269	}
1270	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1271	if (ret) {
1272		wcn36xx_err("hal_delete_sta_self response failed err=%d\n",
1273			    ret);
1274		goto out;
1275	}
1276out:
1277	mutex_unlock(&wcn->hal_mutex);
1278	return ret;
1279}
1280
1281int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index)
1282{
1283	struct wcn36xx_hal_delete_sta_req_msg msg_body;
1284	int ret;
1285
1286	mutex_lock(&wcn->hal_mutex);
1287	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ);
1288
1289	msg_body.sta_index = sta_index;
1290
1291	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1292
1293	wcn36xx_dbg(WCN36XX_DBG_HAL,
1294		    "hal delete sta sta_index %d\n",
1295		    msg_body.sta_index);
1296
1297	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1298	if (ret) {
1299		wcn36xx_err("Sending hal_delete_sta failed\n");
1300		goto out;
1301	}
1302	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1303	if (ret) {
1304		wcn36xx_err("hal_delete_sta response failed err=%d\n", ret);
1305		goto out;
1306	}
1307out:
1308	mutex_unlock(&wcn->hal_mutex);
1309	return ret;
1310}
1311
1312static int wcn36xx_smd_join_rsp(void *buf, size_t len)
1313{
1314	struct wcn36xx_hal_join_rsp_msg *rsp;
1315
1316	if (wcn36xx_smd_rsp_status_check(buf, len))
1317		return -EIO;
1318
1319	rsp = buf;
1320
1321	wcn36xx_dbg(WCN36XX_DBG_HAL,
1322		    "hal rsp join status %d tx_mgmt_power %d\n",
1323		    rsp->status, rsp->tx_mgmt_power);
1324
1325	return 0;
1326}
1327
1328int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch)
1329{
1330	struct wcn36xx_hal_join_req_msg msg_body;
1331	int ret;
1332
1333	mutex_lock(&wcn->hal_mutex);
1334	INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ);
1335
1336	memcpy(&msg_body.bssid, bssid, ETH_ALEN);
1337	memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN);
1338	msg_body.channel = ch;
1339
1340	if (conf_is_ht40_minus(&wcn->hw->conf))
1341		msg_body.secondary_channel_offset =
1342			PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
1343	else if (conf_is_ht40_plus(&wcn->hw->conf))
1344		msg_body.secondary_channel_offset =
1345			PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
1346	else
1347		msg_body.secondary_channel_offset =
1348			PHY_SINGLE_CHANNEL_CENTERED;
1349
1350	msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE;
1351
1352	msg_body.max_tx_power = 0xbf;
1353	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1354
1355	wcn36xx_dbg(WCN36XX_DBG_HAL,
1356		    "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n",
1357		    msg_body.bssid, msg_body.self_sta_mac_addr,
1358		    msg_body.channel, msg_body.link_state);
1359
1360	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1361	if (ret) {
1362		wcn36xx_err("Sending hal_join failed\n");
1363		goto out;
1364	}
1365	ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len);
1366	if (ret) {
1367		wcn36xx_err("hal_join response failed err=%d\n", ret);
1368		goto out;
1369	}
1370out:
1371	mutex_unlock(&wcn->hal_mutex);
1372	return ret;
1373}
1374
1375int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid,
1376			    const u8 *sta_mac,
1377			    enum wcn36xx_hal_link_state state)
1378{
1379	struct wcn36xx_hal_set_link_state_req_msg msg_body;
1380	int ret;
1381
1382	mutex_lock(&wcn->hal_mutex);
1383	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ);
1384
1385	memcpy(&msg_body.bssid, bssid, ETH_ALEN);
1386	memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN);
1387	msg_body.state = state;
1388
1389	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1390
1391	wcn36xx_dbg(WCN36XX_DBG_HAL,
1392		    "hal set link state bssid %pM self_mac_addr %pM state %d\n",
1393		    msg_body.bssid, msg_body.self_mac_addr, msg_body.state);
1394
1395	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1396	if (ret) {
1397		wcn36xx_err("Sending hal_set_link_st failed\n");
1398		goto out;
1399	}
1400	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1401	if (ret) {
1402		wcn36xx_err("hal_set_link_st response failed err=%d\n", ret);
1403		goto out;
1404	}
1405out:
1406	mutex_unlock(&wcn->hal_mutex);
1407	return ret;
1408}
1409
1410static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn,
1411			const struct wcn36xx_hal_config_sta_params *orig,
1412			struct wcn36xx_hal_config_sta_params_v1 *v1)
1413{
1414	/* convert orig to v1 format */
1415	memcpy(&v1->bssid, orig->bssid, ETH_ALEN);
1416	memcpy(&v1->mac, orig->mac, ETH_ALEN);
1417	v1->aid = orig->aid;
1418	v1->type = orig->type;
1419	v1->short_preamble_supported = orig->short_preamble_supported;
1420	v1->listen_interval = orig->listen_interval;
1421	v1->wmm_enabled = orig->wmm_enabled;
1422	v1->ht_capable = orig->ht_capable;
1423	v1->tx_channel_width_set = orig->tx_channel_width_set;
1424	v1->rifs_mode = orig->rifs_mode;
1425	v1->lsig_txop_protection = orig->lsig_txop_protection;
1426	v1->max_ampdu_size = orig->max_ampdu_size;
1427	v1->max_ampdu_density = orig->max_ampdu_density;
1428	v1->sgi_40mhz = orig->sgi_40mhz;
1429	v1->sgi_20Mhz = orig->sgi_20Mhz;
1430	v1->rmf = orig->rmf;
1431	v1->encrypt_type = orig->encrypt_type;
1432	v1->action = orig->action;
1433	v1->uapsd = orig->uapsd;
1434	v1->max_sp_len = orig->max_sp_len;
1435	v1->green_field_capable = orig->green_field_capable;
1436	v1->mimo_ps = orig->mimo_ps;
1437	v1->delayed_ba_support = orig->delayed_ba_support;
1438	v1->max_ampdu_duration = orig->max_ampdu_duration;
1439	v1->dsss_cck_mode_40mhz = orig->dsss_cck_mode_40mhz;
1440	memcpy(&v1->supported_rates, &orig->supported_rates,
1441	       sizeof(orig->supported_rates));
1442	v1->sta_index = orig->sta_index;
1443	v1->bssid_index = orig->bssid_index;
1444	v1->p2p = orig->p2p;
1445}
1446
1447static void
1448wcn36xx_smd_set_sta_params_v1(struct wcn36xx *wcn,
1449			      struct ieee80211_vif *vif,
1450			      struct ieee80211_sta *sta,
1451			      struct wcn36xx_hal_config_sta_params_v1 *sta_par)
1452{
1453	struct wcn36xx_sta *sta_priv = NULL;
1454	struct wcn36xx_hal_config_sta_params sta_par_v0;
1455
1456	wcn36xx_smd_set_sta_params(wcn, vif, sta, &sta_par_v0);
1457	wcn36xx_smd_convert_sta_to_v1(wcn, &sta_par_v0, sta_par);
1458
1459	if (sta) {
1460		sta_priv = wcn36xx_sta_to_priv(sta);
1461		wcn36xx_smd_set_sta_vht_params(wcn, sta, sta_par);
1462		wcn36xx_smd_set_sta_ht_ldpc_params(sta, sta_par);
1463		memcpy(&sta_par->supported_rates, &sta_priv->supported_rates,
1464		       sizeof(sta_par->supported_rates));
1465	} else {
1466		wcn36xx_set_default_rates_v1(&sta_par->supported_rates);
1467		wcn36xx_smd_set_sta_default_vht_params(wcn, sta_par);
1468		wcn36xx_smd_set_sta_default_ht_ldpc_params(wcn, sta_par);
1469	}
1470}
1471
1472static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
1473				      struct ieee80211_sta *sta,
1474				      void *buf,
1475				      size_t len)
1476{
1477	struct wcn36xx_hal_config_sta_rsp_msg *rsp;
1478	struct config_sta_rsp_params *params;
1479	struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1480
1481	if (len < sizeof(*rsp))
1482		return -EINVAL;
1483
1484	rsp = buf;
1485	params = &rsp->params;
1486
1487	if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1488		wcn36xx_warn("hal config sta response failure: %d\n",
1489			     params->status);
1490		return -EIO;
1491	}
1492
1493	sta_priv->sta_index = params->sta_index;
1494	sta_priv->dpu_desc_index = params->dpu_index;
1495	sta_priv->ucast_dpu_sign = params->uc_ucast_sig;
1496
1497	wcn36xx_dbg(WCN36XX_DBG_HAL,
1498		    "hal config sta rsp status %d sta_index %d bssid_index %d uc_ucast_sig %d p2p %d\n",
1499		    params->status, params->sta_index, params->bssid_index,
1500		    params->uc_ucast_sig, params->p2p);
1501
1502	return 0;
1503}
1504
1505static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn,
1506				     struct ieee80211_vif *vif,
1507				     struct ieee80211_sta *sta)
1508{
1509	struct wcn36xx_hal_config_sta_req_msg_v1 msg_body;
1510	struct wcn36xx_hal_config_sta_params_v1 *sta_params;
1511
1512	if (wcn->rf_id == RF_IRIS_WCN3680) {
1513		INIT_HAL_MSG_V1(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
1514	} else {
1515		INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
1516		msg_body.header.len -= WCN36XX_DIFF_STA_PARAMS_V1_NOVHT;
1517	}
1518
1519	sta_params = &msg_body.sta_params;
1520
1521	wcn36xx_smd_set_sta_params_v1(wcn, vif, sta, sta_params);
1522
1523	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1524
1525	wcn36xx_dbg(WCN36XX_DBG_HAL,
1526		    "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1527		    sta_params->action, sta_params->sta_index, sta_params->bssid_index,
1528		    sta_params->bssid, sta_params->type, sta_params->mac, sta_params->aid);
1529
1530	return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1531}
1532
1533static int wcn36xx_smd_config_sta_v0(struct wcn36xx *wcn,
1534				     struct ieee80211_vif *vif,
1535				     struct ieee80211_sta *sta)
1536{
1537	struct wcn36xx_hal_config_sta_req_msg msg;
1538	struct wcn36xx_hal_config_sta_params *sta_params;
1539
1540	INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ);
1541
1542	sta_params = &msg.sta_params;
1543
1544	wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1545
1546	PREPARE_HAL_BUF(wcn->hal_buf, msg);
1547
1548	wcn36xx_dbg(WCN36XX_DBG_HAL,
1549		    "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1550		    sta_params->action, sta_params->sta_index,
1551		    sta_params->bssid_index, sta_params->bssid,
1552		    sta_params->type, sta_params->mac, sta_params->aid);
1553
1554	return wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1555}
1556
1557int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1558			   struct ieee80211_sta *sta)
1559{
1560	int ret;
1561
1562	mutex_lock(&wcn->hal_mutex);
1563
1564	if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24))
1565		ret = wcn36xx_smd_config_sta_v1(wcn, vif, sta);
1566	else
1567		ret = wcn36xx_smd_config_sta_v0(wcn, vif, sta);
1568
1569	if (ret) {
1570		wcn36xx_err("Sending hal_config_sta failed\n");
1571		goto out;
1572	}
1573	ret = wcn36xx_smd_config_sta_rsp(wcn,
1574					 sta,
1575					 wcn->hal_buf,
1576					 wcn->hal_rsp_len);
1577	if (ret) {
1578		wcn36xx_err("hal_config_sta response failed err=%d\n", ret);
1579		goto out;
1580	}
1581out:
1582	mutex_unlock(&wcn->hal_mutex);
1583	return ret;
1584}
1585
1586static void wcn36xx_smd_set_bss_params(struct wcn36xx *wcn,
1587				       struct ieee80211_vif *vif,
1588				       struct ieee80211_sta *sta,
1589				       const u8 *bssid,
1590				       bool update,
1591				       struct wcn36xx_hal_config_bss_params *bss)
1592{
1593	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1594
1595	WARN_ON(is_zero_ether_addr(bssid));
1596
1597	memcpy(&bss->bssid, bssid, ETH_ALEN);
1598
1599	memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN);
1600
1601	if (vif->type == NL80211_IFTYPE_STATION) {
1602		bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE;
1603
1604		/* STA */
1605		bss->oper_mode = 1;
1606		bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE;
1607	} else if (vif->type == NL80211_IFTYPE_AP ||
1608		   vif->type == NL80211_IFTYPE_MESH_POINT) {
1609		bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE;
1610
1611		/* AP */
1612		bss->oper_mode = 0;
1613		bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE;
1614	} else if (vif->type == NL80211_IFTYPE_ADHOC) {
1615		bss->bss_type = WCN36XX_HAL_IBSS_MODE;
1616
1617		/* STA */
1618		bss->oper_mode = 1;
1619	} else {
1620		wcn36xx_warn("Unknown type for bss config: %d\n", vif->type);
1621	}
1622
1623	if (vif->type == NL80211_IFTYPE_STATION)
1624		wcn36xx_smd_set_bss_nw_type(wcn, sta, bss);
1625	else
1626		bss->nw_type = WCN36XX_HAL_11N_NW_TYPE;
1627
1628	bss->short_slot_time_supported = vif->bss_conf.use_short_slot;
1629	bss->lla_coexist = 0;
1630	bss->llb_coexist = 0;
1631	bss->llg_coexist = 0;
1632	bss->rifs_mode = 0;
1633	bss->beacon_interval = vif->bss_conf.beacon_int;
1634	bss->dtim_period = vif_priv->dtim_period;
1635
1636	wcn36xx_smd_set_bss_ht_params(vif, sta, bss);
1637
1638	bss->oper_channel = WCN36XX_HW_CHANNEL(wcn);
1639
1640	if (conf_is_ht40_minus(&wcn->hw->conf))
1641		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
1642	else if (conf_is_ht40_plus(&wcn->hw->conf))
1643		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
1644	else
1645		bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE;
1646
1647	bss->reserved = 0;
1648
1649	/* wcn->ssid is only valid in AP and IBSS mode */
1650	bss->ssid.length = vif_priv->ssid.length;
1651	memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length);
1652
1653	bss->obss_prot_enabled = 0;
1654	bss->rmf = 0;
1655	bss->max_probe_resp_retry_limit = 0;
1656	bss->hidden_ssid = vif->bss_conf.hidden_ssid;
1657	bss->proxy_probe_resp = 0;
1658	bss->edca_params_valid = 0;
1659
1660	/* FIXME: set acbe, acbk, acvi and acvo */
1661
1662	bss->ext_set_sta_key_param_valid = 0;
1663
1664	/* FIXME: set ext_set_sta_key_param */
1665
1666	bss->spectrum_mgt_enable = 0;
1667	bss->tx_mgmt_power = 0;
1668	bss->max_tx_power = WCN36XX_MAX_POWER(wcn);
1669	bss->action = update;
1670
1671	vif_priv->bss_type = bss->bss_type;
1672}
1673
1674static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
1675				     struct ieee80211_vif *vif,
1676				     struct ieee80211_sta *sta_80211,
1677				     const u8 *bssid,
1678				     bool update)
1679{
1680	struct wcn36xx_hal_config_bss_req_msg_v1 *msg_body;
1681	struct wcn36xx_hal_config_bss_params_v1 *bss;
1682	struct wcn36xx_hal_config_bss_params bss_v0;
1683	struct wcn36xx_hal_config_sta_params_v1 *sta;
1684	struct cfg80211_chan_def *chandef;
1685	int ret;
1686
1687	msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
1688	if (!msg_body)
1689		return -ENOMEM;
1690
1691	if (wcn->rf_id == RF_IRIS_WCN3680) {
1692		INIT_HAL_MSG_V1((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ);
1693	} else {
1694		INIT_HAL_MSG((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ);
1695		msg_body->header.len -= WCN36XX_DIFF_BSS_PARAMS_V1_NOVHT;
1696	}
1697
1698	bss = &msg_body->bss_params;
1699	sta = &bss->sta;
1700
1701	memset(&bss_v0, 0x00, sizeof(bss_v0));
1702	wcn36xx_smd_set_bss_params(wcn, vif, sta_80211, bssid, update, &bss_v0);
1703	wcn36xx_smd_set_sta_params_v1(wcn, vif, sta_80211, sta);
1704
1705	/* convert orig to v1 */
1706	memcpy(bss->bssid, &bss_v0.bssid, ETH_ALEN);
1707	memcpy(bss->self_mac_addr, &bss_v0.self_mac_addr, ETH_ALEN);
1708
1709	bss->bss_type = bss_v0.bss_type;
1710	bss->oper_mode = bss_v0.oper_mode;
1711	bss->nw_type = bss_v0.nw_type;
1712
1713	bss->short_slot_time_supported =
1714		bss_v0.short_slot_time_supported;
1715	bss->lla_coexist = bss_v0.lla_coexist;
1716	bss->llb_coexist = bss_v0.llb_coexist;
1717	bss->llg_coexist = bss_v0.llg_coexist;
1718	bss->ht20_coexist = bss_v0.ht20_coexist;
1719	bss->lln_non_gf_coexist = bss_v0.lln_non_gf_coexist;
1720
1721	bss->lsig_tx_op_protection_full_support =
1722		bss_v0.lsig_tx_op_protection_full_support;
1723	bss->rifs_mode = bss_v0.rifs_mode;
1724	bss->beacon_interval = bss_v0.beacon_interval;
1725	bss->dtim_period = bss_v0.dtim_period;
1726	bss->tx_channel_width_set = bss_v0.tx_channel_width_set;
1727	bss->oper_channel = bss_v0.oper_channel;
1728
1729	if (wcn->hw->conf.chandef.width == NL80211_CHAN_WIDTH_80) {
1730		chandef = &wcn->hw->conf.chandef;
1731		bss->ext_channel = HW_VALUE_PHY(chandef->chan->hw_value);
1732	} else {
1733		bss->ext_channel = bss_v0.ext_channel;
1734	}
1735
1736	bss->reserved = bss_v0.reserved;
1737
1738	memcpy(&bss->ssid, &bss_v0.ssid,
1739	       sizeof(bss_v0.ssid));
1740
1741	bss->action = bss_v0.action;
1742	bss->rateset = bss_v0.rateset;
1743	bss->ht = bss_v0.ht;
1744	bss->obss_prot_enabled = bss_v0.obss_prot_enabled;
1745	bss->rmf = bss_v0.rmf;
1746	bss->ht_oper_mode = bss_v0.ht_oper_mode;
1747	bss->dual_cts_protection = bss_v0.dual_cts_protection;
1748
1749	bss->max_probe_resp_retry_limit =
1750		bss_v0.max_probe_resp_retry_limit;
1751	bss->hidden_ssid = bss_v0.hidden_ssid;
1752	bss->proxy_probe_resp =	bss_v0.proxy_probe_resp;
1753	bss->edca_params_valid = bss_v0.edca_params_valid;
1754
1755	memcpy(&bss->acbe, &bss_v0.acbe,
1756	       sizeof(bss_v0.acbe));
1757	memcpy(&bss->acbk, &bss_v0.acbk,
1758	       sizeof(bss_v0.acbk));
1759	memcpy(&bss->acvi, &bss_v0.acvi,
1760	       sizeof(bss_v0.acvi));
1761	memcpy(&bss->acvo, &bss_v0.acvo,
1762	       sizeof(bss_v0.acvo));
1763
1764	bss->ext_set_sta_key_param_valid =
1765		bss_v0.ext_set_sta_key_param_valid;
1766
1767	memcpy(&bss->ext_set_sta_key_param,
1768	       &bss_v0.ext_set_sta_key_param,
1769	       sizeof(bss_v0.acvo));
1770
1771	bss->wcn36xx_hal_persona = bss_v0.wcn36xx_hal_persona;
1772	bss->spectrum_mgt_enable = bss_v0.spectrum_mgt_enable;
1773	bss->tx_mgmt_power = bss_v0.tx_mgmt_power;
1774	bss->max_tx_power = bss_v0.max_tx_power;
1775
1776	wcn36xx_smd_set_bss_vht_params(vif, sta_80211, bss);
1777
1778	PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
1779
1780	wcn36xx_dbg(WCN36XX_DBG_HAL,
1781		    "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1782		    bss->bssid, bss->self_mac_addr, bss->bss_type,
1783		    bss->oper_mode, bss->nw_type);
1784
1785	wcn36xx_dbg(WCN36XX_DBG_HAL,
1786		    "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1787		    sta->bssid, sta->action, sta->sta_index,
1788		    sta->bssid_index, sta->aid, sta->type, sta->mac);
1789
1790	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
1791	kfree(msg_body);
1792
1793	return ret;
1794}
1795
1796static int wcn36xx_smd_config_bss_v0(struct wcn36xx *wcn,
1797				     struct ieee80211_vif *vif,
1798				     struct ieee80211_sta *sta,
1799				     const u8 *bssid,
1800				     bool update)
1801{
1802	struct wcn36xx_hal_config_bss_req_msg *msg;
1803	struct wcn36xx_hal_config_bss_params *bss;
1804	struct wcn36xx_hal_config_sta_params *sta_params;
1805	int ret;
1806
1807	msg = kzalloc(sizeof(*msg), GFP_KERNEL);
1808	if (!msg)
1809		return -ENOMEM;
1810
1811	INIT_HAL_MSG((*msg), WCN36XX_HAL_CONFIG_BSS_REQ);
1812
1813	bss = &msg->bss_params;
1814	sta_params = &bss->sta;
1815
1816	wcn36xx_smd_set_bss_params(wcn, vif, sta, bssid, update, bss);
1817	wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1818
1819	PREPARE_HAL_BUF(wcn->hal_buf, (*msg));
1820
1821	wcn36xx_dbg(WCN36XX_DBG_HAL,
1822		    "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1823		    bss->bssid, bss->self_mac_addr, bss->bss_type,
1824		    bss->oper_mode, bss->nw_type);
1825
1826	wcn36xx_dbg(WCN36XX_DBG_HAL,
1827		    "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1828		    sta_params->bssid, sta_params->action,
1829		    sta_params->sta_index, sta_params->bssid_index,
1830		    sta_params->aid, sta_params->type,
1831		    sta_params->mac);
1832
1833	ret = wcn36xx_smd_send_and_wait(wcn, msg->header.len);
1834	kfree(msg);
1835
1836	return ret;
1837}
1838
1839static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
1840				      struct ieee80211_vif *vif,
1841				      struct ieee80211_sta *sta,
1842				      void *buf,
1843				      size_t len)
1844{
1845	struct wcn36xx_hal_config_bss_rsp_msg *rsp;
1846	struct wcn36xx_hal_config_bss_rsp_params *params;
1847	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1848
1849	if (len < sizeof(*rsp))
1850		return -EINVAL;
1851
1852	rsp = buf;
1853	params = &rsp->bss_rsp_params;
1854
1855	if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1856		wcn36xx_warn("hal config bss response failure: %d\n",
1857			     params->status);
1858		return -EIO;
1859	}
1860
1861	wcn36xx_dbg(WCN36XX_DBG_HAL,
1862		    "hal config bss rsp status %d bss_idx %d dpu_desc_index %d"
1863		    " sta_idx %d self_idx %d bcast_idx %d mac %pM"
1864		    " power %d ucast_dpu_signature %d\n",
1865		    params->status, params->bss_index, params->dpu_desc_index,
1866		    params->bss_sta_index, params->bss_self_sta_index,
1867		    params->bss_bcast_sta_idx, params->mac,
1868		    params->tx_mgmt_power, params->ucast_dpu_signature);
1869
1870	vif_priv->bss_index = params->bss_index;
1871
1872	if (sta) {
1873		struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1874		sta_priv->bss_sta_index = params->bss_sta_index;
1875		sta_priv->bss_dpu_desc_index = params->dpu_desc_index;
1876	}
1877
1878	vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature;
1879
1880	return 0;
1881}
1882
1883int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1884			   struct ieee80211_sta *sta, const u8 *bssid,
1885			   bool update)
1886{
1887	int ret;
1888
1889	mutex_lock(&wcn->hal_mutex);
1890
1891	if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24))
1892		ret = wcn36xx_smd_config_bss_v1(wcn, vif, sta, bssid, update);
1893	else
1894		ret = wcn36xx_smd_config_bss_v0(wcn, vif, sta, bssid, update);
1895
1896	if (ret) {
1897		wcn36xx_err("Sending hal_config_bss failed\n");
1898		goto out;
1899	}
1900	ret = wcn36xx_smd_config_bss_rsp(wcn,
1901					 vif,
1902					 sta,
1903					 wcn->hal_buf,
1904					 wcn->hal_rsp_len);
1905	if (ret)
1906		wcn36xx_err("hal_config_bss response failed err=%d\n", ret);
1907
1908out:
1909	mutex_unlock(&wcn->hal_mutex);
1910	return ret;
1911}
1912
1913int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1914{
1915	struct wcn36xx_hal_delete_bss_req_msg msg_body;
1916	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1917	int ret = 0;
1918
1919	mutex_lock(&wcn->hal_mutex);
1920
1921	if (vif_priv->bss_index == WCN36XX_HAL_BSS_INVALID_IDX)
1922		goto out;
1923
1924	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ);
1925
1926	msg_body.bss_index = vif_priv->bss_index;
1927
1928	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1929
1930	wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index);
1931
1932	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1933	if (ret) {
1934		wcn36xx_err("Sending hal_delete_bss failed\n");
1935		goto out;
1936	}
1937	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1938	if (ret) {
1939		wcn36xx_err("hal_delete_bss response failed err=%d\n", ret);
1940		goto out;
1941	}
1942
1943	vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
1944out:
1945	mutex_unlock(&wcn->hal_mutex);
1946	return ret;
1947}
1948
1949int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1950			    struct sk_buff *skb_beacon, u16 tim_off,
1951			    u16 p2p_off)
1952{
1953	struct wcn36xx_hal_send_beacon_req_msg msg_body;
1954	int ret, pad, pvm_len;
1955
1956	mutex_lock(&wcn->hal_mutex);
1957	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
1958
1959	pvm_len = skb_beacon->data[tim_off + 1] - 3;
1960	pad = TIM_MIN_PVM_SIZE - pvm_len;
1961
1962	/* Padding is irrelevant to mesh mode since tim_off is always 0. */
1963	if (vif->type == NL80211_IFTYPE_MESH_POINT)
1964		pad = 0;
1965
1966	msg_body.beacon_length = skb_beacon->len + pad;
1967	/* TODO need to find out why + 6 is needed */
1968	msg_body.beacon_length6 = msg_body.beacon_length + 6;
1969
1970	if (msg_body.beacon_length > BEACON_TEMPLATE_SIZE) {
1971		wcn36xx_err("Beacon is too big: beacon size=%d\n",
1972			      msg_body.beacon_length);
1973		ret = -ENOMEM;
1974		goto out;
1975	}
1976	memcpy(msg_body.beacon, skb_beacon->data, skb_beacon->len);
1977	memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
1978
1979	if (pad > 0) {
1980		/*
1981		 * The wcn36xx FW has a fixed size for the PVM in the TIM. If
1982		 * given the beacon template from mac80211 with a PVM shorter
1983		 * than the FW expectes it will overwrite the data after the
1984		 * TIM.
1985		 */
1986		wcn36xx_dbg(WCN36XX_DBG_HAL, "Pad TIM PVM. %d bytes at %d\n",
1987			    pad, pvm_len);
1988		memmove(&msg_body.beacon[tim_off + 5 + pvm_len + pad],
1989			&msg_body.beacon[tim_off + 5 + pvm_len],
1990			skb_beacon->len - (tim_off + 5 + pvm_len));
1991		memset(&msg_body.beacon[tim_off + 5 + pvm_len], 0, pad);
1992		msg_body.beacon[tim_off + 1] += pad;
1993	}
1994
1995	/* TODO need to find out why this is needed? */
1996	if (vif->type == NL80211_IFTYPE_MESH_POINT)
1997		/* mesh beacon don't need this, so push further down */
1998		msg_body.tim_ie_offset = 256;
1999	else
2000		msg_body.tim_ie_offset = tim_off+4;
2001	msg_body.p2p_ie_offset = p2p_off;
2002	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2003
2004	wcn36xx_dbg(WCN36XX_DBG_HAL,
2005		    "hal send beacon beacon_length %d\n",
2006		    msg_body.beacon_length);
2007
2008	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2009	if (ret) {
2010		wcn36xx_err("Sending hal_send_beacon failed\n");
2011		goto out;
2012	}
2013	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2014	if (ret) {
2015		wcn36xx_err("hal_send_beacon response failed err=%d\n", ret);
2016		goto out;
2017	}
2018out:
2019	mutex_unlock(&wcn->hal_mutex);
2020	return ret;
2021}
2022
2023int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn,
2024				      struct ieee80211_vif *vif,
2025				      struct sk_buff *skb)
2026{
2027	struct wcn36xx_hal_send_probe_resp_req_msg msg;
2028	int ret;
2029
2030	mutex_lock(&wcn->hal_mutex);
2031	INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ);
2032
2033	if (skb->len > BEACON_TEMPLATE_SIZE) {
2034		wcn36xx_warn("probe response template is too big: %d\n",
2035			     skb->len);
2036		ret = -E2BIG;
2037		goto out;
2038	}
2039
2040	msg.probe_resp_template_len = skb->len;
2041	memcpy(&msg.probe_resp_template, skb->data, skb->len);
2042
2043	memcpy(msg.bssid, vif->addr, ETH_ALEN);
2044
2045	PREPARE_HAL_BUF(wcn->hal_buf, msg);
2046
2047	wcn36xx_dbg(WCN36XX_DBG_HAL,
2048		    "hal update probe rsp len %d bssid %pM\n",
2049		    msg.probe_resp_template_len, msg.bssid);
2050
2051	ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
2052	if (ret) {
2053		wcn36xx_err("Sending hal_update_proberesp_tmpl 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_update_proberesp_tmpl response failed err=%d\n",
2059			    ret);
2060		goto out;
2061	}
2062out:
2063	mutex_unlock(&wcn->hal_mutex);
2064	return ret;
2065}
2066
2067int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
2068			   enum ani_ed_type enc_type,
2069			   u8 keyidx,
2070			   u8 keylen,
2071			   u8 *key,
2072			   u8 sta_index)
2073{
2074	struct wcn36xx_hal_set_sta_key_req_msg msg_body;
2075	int ret;
2076
2077	mutex_lock(&wcn->hal_mutex);
2078	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ);
2079
2080	msg_body.set_sta_key_params.sta_index = sta_index;
2081	msg_body.set_sta_key_params.enc_type = enc_type;
2082
2083	if (enc_type == WCN36XX_HAL_ED_WEP104 ||
2084	    enc_type == WCN36XX_HAL_ED_WEP40) {
2085		/* Use bss key for wep (static) */
2086		msg_body.set_sta_key_params.def_wep_idx = keyidx;
2087		msg_body.set_sta_key_params.wep_type = 0;
2088	} else {
2089		msg_body.set_sta_key_params.key[0].id = keyidx;
2090		msg_body.set_sta_key_params.key[0].unicast = 1;
2091		msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
2092		msg_body.set_sta_key_params.key[0].pae_role = 0;
2093		msg_body.set_sta_key_params.key[0].length = keylen;
2094		memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
2095	}
2096
2097	msg_body.set_sta_key_params.single_tid_rc = 1;
2098
2099	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2100
2101	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2102	if (ret) {
2103		wcn36xx_err("Sending hal_set_stakey failed\n");
2104		goto out;
2105	}
2106	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2107	if (ret) {
2108		wcn36xx_err("hal_set_stakey response failed err=%d\n", ret);
2109		goto out;
2110	}
2111out:
2112	mutex_unlock(&wcn->hal_mutex);
2113	return ret;
2114}
2115
2116int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn,
2117			   enum ani_ed_type enc_type,
2118			   u8 bssidx,
2119			   u8 keyidx,
2120			   u8 keylen,
2121			   u8 *key)
2122{
2123	struct wcn36xx_hal_set_bss_key_req_msg msg_body;
2124	int ret;
2125
2126	mutex_lock(&wcn->hal_mutex);
2127	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ);
2128	msg_body.bss_idx = bssidx;
2129	msg_body.enc_type = enc_type;
2130	msg_body.num_keys = 1;
2131	msg_body.keys[0].id = keyidx;
2132	msg_body.keys[0].unicast = 0;
2133	msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY;
2134	msg_body.keys[0].pae_role = 0;
2135	msg_body.keys[0].length = keylen;
2136	memcpy(msg_body.keys[0].key, key, keylen);
2137
2138	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2139
2140	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2141	if (ret) {
2142		wcn36xx_err("Sending hal_set_bsskey failed\n");
2143		goto out;
2144	}
2145	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2146	if (ret) {
2147		wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret);
2148		goto out;
2149	}
2150out:
2151	mutex_unlock(&wcn->hal_mutex);
2152	return ret;
2153}
2154
2155int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn,
2156			      enum ani_ed_type enc_type,
2157			      u8 keyidx,
2158			      u8 sta_index)
2159{
2160	struct wcn36xx_hal_remove_sta_key_req_msg msg_body;
2161	int ret;
2162
2163	mutex_lock(&wcn->hal_mutex);
2164	INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ);
2165
2166	msg_body.sta_idx = sta_index;
2167	msg_body.enc_type = enc_type;
2168	msg_body.key_id = keyidx;
2169
2170	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2171
2172	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2173	if (ret) {
2174		wcn36xx_err("Sending hal_remove_stakey failed\n");
2175		goto out;
2176	}
2177	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2178	if (ret) {
2179		wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret);
2180		goto out;
2181	}
2182out:
2183	mutex_unlock(&wcn->hal_mutex);
2184	return ret;
2185}
2186
2187int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
2188			      enum ani_ed_type enc_type,
2189			      u8 bssidx,
2190			      u8 keyidx)
2191{
2192	struct wcn36xx_hal_remove_bss_key_req_msg msg_body;
2193	int ret;
2194
2195	mutex_lock(&wcn->hal_mutex);
2196	INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ);
2197	msg_body.bss_idx = bssidx;
2198	msg_body.enc_type = enc_type;
2199	msg_body.key_id = keyidx;
2200
2201	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2202
2203	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2204	if (ret) {
2205		wcn36xx_err("Sending hal_remove_bsskey failed\n");
2206		goto out;
2207	}
2208	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2209	if (ret) {
2210		wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
2211		goto out;
2212	}
2213out:
2214	mutex_unlock(&wcn->hal_mutex);
2215	return ret;
2216}
2217
2218int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
2219{
2220	struct wcn36xx_hal_enter_bmps_req_msg msg_body;
2221	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2222	int ret;
2223
2224	mutex_lock(&wcn->hal_mutex);
2225	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ);
2226
2227	msg_body.bss_index = vif_priv->bss_index;
2228	msg_body.tbtt = vif->bss_conf.sync_tsf;
2229	msg_body.dtim_period = vif_priv->dtim_period;
2230
2231	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2232
2233	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2234	if (ret) {
2235		wcn36xx_err("Sending hal_enter_bmps failed\n");
2236		goto out;
2237	}
2238	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2239	if (ret) {
2240		wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret);
2241		goto out;
2242	}
2243out:
2244	mutex_unlock(&wcn->hal_mutex);
2245	return ret;
2246}
2247
2248int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
2249{
2250	struct wcn36xx_hal_exit_bmps_req_msg msg_body;
2251	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2252	int ret;
2253
2254	mutex_lock(&wcn->hal_mutex);
2255	INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ);
2256
2257	msg_body.bss_index = vif_priv->bss_index;
2258	msg_body.send_data_null = 1;
2259
2260	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2261
2262	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2263	if (ret) {
2264		wcn36xx_err("Sending hal_exit_bmps failed\n");
2265		goto out;
2266	}
2267	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2268	if (ret) {
2269		wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
2270		goto out;
2271	}
2272out:
2273	mutex_unlock(&wcn->hal_mutex);
2274	return ret;
2275}
2276
2277int wcn36xx_smd_enter_imps(struct wcn36xx *wcn)
2278{
2279	struct wcn36xx_hal_enter_imps_req_msg msg_body;
2280	int ret;
2281
2282	mutex_lock(&wcn->hal_mutex);
2283	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_IMPS_REQ);
2284
2285	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2286
2287	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2288	if (ret) {
2289		wcn36xx_err("Sending hal_enter_imps failed\n");
2290		goto out;
2291	}
2292	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2293	if (ret) {
2294		wcn36xx_err("hal_enter_imps response failed err=%d\n", ret);
2295		goto out;
2296	}
2297
2298	wcn36xx_dbg(WCN36XX_DBG_HAL, "Entered idle mode\n");
2299out:
2300	mutex_unlock(&wcn->hal_mutex);
2301	return ret;
2302}
2303
2304int wcn36xx_smd_exit_imps(struct wcn36xx *wcn)
2305{
2306	struct wcn36xx_hal_exit_imps_req_msg msg_body;
2307	int ret;
2308
2309	mutex_lock(&wcn->hal_mutex);
2310	INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_IMPS_REQ);
2311
2312	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2313
2314	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2315	if (ret) {
2316		wcn36xx_err("Sending hal_exit_imps failed\n");
2317		goto out;
2318	}
2319	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2320	if (ret) {
2321		wcn36xx_err("hal_exit_imps response failed err=%d\n", ret);
2322		goto out;
2323	}
2324	wcn36xx_dbg(WCN36XX_DBG_HAL, "Exited idle mode\n");
2325out:
2326	mutex_unlock(&wcn->hal_mutex);
2327	return ret;
2328}
2329
2330int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim)
2331{
2332	struct wcn36xx_hal_set_power_params_req_msg msg_body;
2333	int ret;
2334
2335	mutex_lock(&wcn->hal_mutex);
2336	INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ);
2337
2338	/*
2339	 * When host is down ignore every second dtim
2340	 */
2341	if (ignore_dtim) {
2342		msg_body.ignore_dtim = 1;
2343		msg_body.dtim_period = 2;
2344	}
2345	msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
2346
2347	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2348
2349	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2350	if (ret) {
2351		wcn36xx_err("Sending hal_set_power_params failed\n");
2352		goto out;
2353	}
2354
2355out:
2356	mutex_unlock(&wcn->hal_mutex);
2357	return ret;
2358}
2359
2360/* Notice: This function should be called after associated, or else it
2361 * will be invalid
2362 */
2363int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
2364			       struct ieee80211_vif *vif,
2365			       int packet_type)
2366{
2367	struct wcn36xx_hal_keep_alive_req_msg msg_body;
2368	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2369	int ret;
2370
2371	mutex_lock(&wcn->hal_mutex);
2372	INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ);
2373
2374	if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) {
2375		msg_body.bss_index = vif_priv->bss_index;
2376		msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT;
2377		msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD;
2378	} else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) {
2379		/* TODO: it also support ARP response type */
2380	} else {
2381		wcn36xx_warn("unknown keep alive packet type %d\n", packet_type);
2382		ret = -EINVAL;
2383		goto out;
2384	}
2385
2386	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2387
2388	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2389	if (ret) {
2390		wcn36xx_err("Sending hal_keep_alive failed\n");
2391		goto out;
2392	}
2393	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2394	if (ret) {
2395		wcn36xx_err("hal_keep_alive response failed err=%d\n", ret);
2396		goto out;
2397	}
2398out:
2399	mutex_unlock(&wcn->hal_mutex);
2400	return ret;
2401}
2402
2403int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
2404			     u32 arg3, u32 arg4, u32 arg5)
2405{
2406	struct wcn36xx_hal_dump_cmd_req_msg msg_body;
2407	int ret;
2408
2409	mutex_lock(&wcn->hal_mutex);
2410	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ);
2411
2412	msg_body.arg1 = arg1;
2413	msg_body.arg2 = arg2;
2414	msg_body.arg3 = arg3;
2415	msg_body.arg4 = arg4;
2416	msg_body.arg5 = arg5;
2417
2418	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2419
2420	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2421	if (ret) {
2422		wcn36xx_err("Sending hal_dump_cmd failed\n");
2423		goto out;
2424	}
2425	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2426	if (ret) {
2427		wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret);
2428		goto out;
2429	}
2430out:
2431	mutex_unlock(&wcn->hal_mutex);
2432	return ret;
2433}
2434
2435int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
2436{
2437	struct wcn36xx_hal_feat_caps_msg msg_body, *rsp;
2438	int ret, i;
2439
2440	mutex_lock(&wcn->hal_mutex);
2441	INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
2442
2443	wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
2444	if (wcn->rf_id == RF_IRIS_WCN3680) {
2445		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, DOT11AC);
2446		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, WLAN_CH144);
2447		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps,
2448					       ANTENNA_DIVERSITY_SELECTION);
2449	}
2450
2451	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2452
2453	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2454	if (ret) {
2455		wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
2456		goto out;
2457	}
2458	if (wcn->hal_rsp_len != sizeof(*rsp)) {
2459		wcn36xx_err("Invalid hal_feature_caps_exchange response");
2460		goto out;
2461	}
2462
2463	rsp = (struct wcn36xx_hal_feat_caps_msg *) wcn->hal_buf;
2464
2465	for (i = 0; i < WCN36XX_HAL_CAPS_SIZE; i++)
2466		wcn->fw_feat_caps[i] = rsp->feat_caps[i];
2467out:
2468	mutex_unlock(&wcn->hal_mutex);
2469	return ret;
2470}
2471
2472static int wcn36xx_smd_add_ba_session_rsp(void *buf, int len, u8 *session)
2473{
2474	struct wcn36xx_hal_add_ba_session_rsp_msg *rsp;
2475
2476	if (len < sizeof(*rsp))
2477		return -EINVAL;
2478
2479	rsp = buf;
2480	if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS)
2481		return rsp->status;
2482
2483	*session = rsp->ba_session_id;
2484
2485	return 0;
2486}
2487
2488int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
2489		struct ieee80211_sta *sta,
2490		u16 tid,
2491		u16 *ssn,
2492		u8 direction,
2493		u8 sta_index)
2494{
2495	struct wcn36xx_hal_add_ba_session_req_msg msg_body;
2496	u8 session_id;
2497	int ret;
2498
2499	mutex_lock(&wcn->hal_mutex);
2500	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ);
2501
2502	msg_body.sta_index = sta_index;
2503	memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN);
2504	msg_body.dialog_token = 0x10;
2505	msg_body.tid = tid;
2506
2507	/* Immediate BA because Delayed BA is not supported */
2508	msg_body.policy = 1;
2509	msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE;
2510	msg_body.timeout = 0;
2511	if (ssn)
2512		msg_body.ssn = *ssn;
2513	msg_body.direction = direction;
2514
2515	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2516
2517	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2518	if (ret) {
2519		wcn36xx_err("Sending hal_add_ba_session failed\n");
2520		goto out;
2521	}
2522	ret = wcn36xx_smd_add_ba_session_rsp(wcn->hal_buf, wcn->hal_rsp_len,
2523					     &session_id);
2524	if (ret) {
2525		wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret);
2526		ret = -EINVAL;
2527		goto out;
2528	}
2529
2530	ret = session_id;
2531out:
2532	mutex_unlock(&wcn->hal_mutex);
2533	return ret;
2534}
2535
2536int wcn36xx_smd_add_ba(struct wcn36xx *wcn, u8 session_id)
2537{
2538	struct wcn36xx_hal_add_ba_req_msg msg_body;
2539	int ret;
2540
2541	mutex_lock(&wcn->hal_mutex);
2542	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ);
2543
2544	msg_body.session_id = session_id;
2545	msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE;
2546
2547	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2548
2549	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2550	if (ret) {
2551		wcn36xx_err("Sending hal_add_ba failed\n");
2552		goto out;
2553	}
2554	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2555	if (ret) {
2556		wcn36xx_err("hal_add_ba response failed err=%d\n", ret);
2557		goto out;
2558	}
2559out:
2560	mutex_unlock(&wcn->hal_mutex);
2561	return ret;
2562}
2563
2564int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 direction, u8 sta_index)
2565{
2566	struct wcn36xx_hal_del_ba_req_msg msg_body;
2567	int ret;
2568
2569	mutex_lock(&wcn->hal_mutex);
2570	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ);
2571
2572	msg_body.sta_index = sta_index;
2573	msg_body.tid = tid;
2574	msg_body.direction = direction;
2575	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2576
2577	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2578	if (ret) {
2579		wcn36xx_err("Sending hal_del_ba failed\n");
2580		goto out;
2581	}
2582	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2583	if (ret) {
2584		wcn36xx_err("hal_del_ba response failed err=%d\n", ret);
2585		goto out;
2586	}
2587out:
2588	mutex_unlock(&wcn->hal_mutex);
2589	return ret;
2590}
2591
2592int wcn36xx_smd_get_stats(struct wcn36xx *wcn, u8 sta_index, u32 stats_mask,
2593			  struct station_info *sinfo)
2594{
2595	struct wcn36xx_hal_stats_req_msg msg_body;
2596	struct wcn36xx_hal_stats_rsp_msg *rsp;
2597	void *rsp_body;
2598	int ret;
2599
2600	if (stats_mask & ~HAL_GLOBAL_CLASS_A_STATS_INFO) {
2601		wcn36xx_err("stats_mask 0x%x contains unimplemented types\n",
2602			    stats_mask);
2603		return -EINVAL;
2604	}
2605
2606	mutex_lock(&wcn->hal_mutex);
2607	INIT_HAL_MSG(msg_body, WCN36XX_HAL_GET_STATS_REQ);
2608
2609	msg_body.sta_id = sta_index;
2610	msg_body.stats_mask = stats_mask;
2611
2612	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2613
2614	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2615	if (ret) {
2616		wcn36xx_err("sending hal_get_stats failed\n");
2617		goto out;
2618	}
2619
2620	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2621	if (ret) {
2622		wcn36xx_err("hal_get_stats response failed err=%d\n", ret);
2623		goto out;
2624	}
2625
2626	rsp = (struct wcn36xx_hal_stats_rsp_msg *)wcn->hal_buf;
2627	rsp_body = (wcn->hal_buf + sizeof(struct wcn36xx_hal_stats_rsp_msg));
2628
2629	if (rsp->stats_mask != stats_mask) {
2630		wcn36xx_err("stats_mask 0x%x differs from requested 0x%x\n",
2631			    rsp->stats_mask, stats_mask);
2632		goto out;
2633	}
2634
2635	if (rsp->stats_mask & HAL_GLOBAL_CLASS_A_STATS_INFO) {
2636		struct ani_global_class_a_stats_info *stats_info = rsp_body;
2637
2638		wcn36xx_process_tx_rate(stats_info, &sinfo->txrate);
2639		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
2640		rsp_body += sizeof(struct ani_global_class_a_stats_info);
2641	}
2642out:
2643	mutex_unlock(&wcn->hal_mutex);
2644
2645	return ret;
2646}
2647
2648static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len, struct add_ba_info *ba_info)
2649{
2650	struct wcn36xx_hal_trigger_ba_rsp_candidate *candidate;
2651	struct wcn36xx_hal_trigger_ba_rsp_msg *rsp;
2652	int i;
2653
2654	if (len < sizeof(*rsp))
2655		return -EINVAL;
2656
2657	rsp = buf;
2658
2659	if (rsp->candidate_cnt < 1)
2660		return rsp->status ? rsp->status : -EINVAL;
2661
2662	candidate = (struct wcn36xx_hal_trigger_ba_rsp_candidate *)(buf + sizeof(*rsp));
2663
2664	for (i = 0; i < STACFG_MAX_TC; i++) {
2665		ba_info[i] = candidate->ba_info[i];
2666	}
2667
2668	return rsp->status;
2669}
2670
2671int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u16 *ssn)
2672{
2673	struct wcn36xx_hal_trigger_ba_req_msg msg_body;
2674	struct wcn36xx_hal_trigger_ba_req_candidate *candidate;
2675	struct add_ba_info ba_info[STACFG_MAX_TC];
2676	int ret;
2677
2678	if (tid >= STACFG_MAX_TC)
2679		return -EINVAL;
2680
2681	mutex_lock(&wcn->hal_mutex);
2682	INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
2683
2684	msg_body.session_id = 0; /* not really used */
2685	msg_body.candidate_cnt = 1;
2686	msg_body.header.len += sizeof(*candidate);
2687	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2688
2689	candidate = (struct wcn36xx_hal_trigger_ba_req_candidate *)
2690		(wcn->hal_buf + sizeof(msg_body));
2691	candidate->sta_index = sta_index;
2692	candidate->tid_bitmap = 1 << tid;
2693
2694	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2695	if (ret) {
2696		wcn36xx_err("Sending hal_trigger_ba failed\n");
2697		goto out;
2698	}
2699	ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len, ba_info);
2700	if (ret) {
2701		wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
2702		goto out;
2703	}
2704out:
2705	mutex_unlock(&wcn->hal_mutex);
2706
2707	if (ssn)
2708		*ssn = ba_info[tid].starting_seq_num;
2709
2710	return ret;
2711}
2712
2713static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len)
2714{
2715	struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf;
2716
2717	if (len != sizeof(*rsp)) {
2718		wcn36xx_warn("Bad TX complete indication\n");
2719		return -EIO;
2720	}
2721
2722	wcn36xx_dxe_tx_ack_ind(wcn, rsp->status);
2723
2724	return 0;
2725}
2726
2727static int wcn36xx_smd_hw_scan_ind(struct wcn36xx *wcn, void *buf, size_t len)
2728{
2729	struct wcn36xx_hal_scan_offload_ind *rsp = buf;
2730	struct cfg80211_scan_info scan_info = {};
2731
2732	if (len != sizeof(*rsp)) {
2733		wcn36xx_warn("Corrupted delete scan indication\n");
2734		return -EIO;
2735	}
2736
2737	wcn36xx_dbg(WCN36XX_DBG_HAL, "scan indication (type %x)\n", rsp->type);
2738
2739	switch (rsp->type) {
2740	case WCN36XX_HAL_SCAN_IND_FAILED:
2741	case WCN36XX_HAL_SCAN_IND_DEQUEUED:
2742		scan_info.aborted = true;
2743		fallthrough;
2744	case WCN36XX_HAL_SCAN_IND_COMPLETED:
2745		mutex_lock(&wcn->scan_lock);
2746		wcn->scan_req = NULL;
2747		if (wcn->scan_aborted)
2748			scan_info.aborted = true;
2749		mutex_unlock(&wcn->scan_lock);
2750		ieee80211_scan_completed(wcn->hw, &scan_info);
2751		break;
2752	case WCN36XX_HAL_SCAN_IND_STARTED:
2753	case WCN36XX_HAL_SCAN_IND_FOREIGN_CHANNEL:
2754	case WCN36XX_HAL_SCAN_IND_PREEMPTED:
2755	case WCN36XX_HAL_SCAN_IND_RESTARTED:
2756		break;
2757	default:
2758		wcn36xx_warn("Unknown scan indication type %x\n", rsp->type);
2759	}
2760
2761	return 0;
2762}
2763
2764static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
2765					 void *buf,
2766					 size_t len)
2767{
2768	struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf;
2769	struct ieee80211_vif *vif = NULL;
2770	struct wcn36xx_vif *tmp;
2771
2772	/* Old FW does not have bss index */
2773	if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
2774		list_for_each_entry(tmp, &wcn->vif_list, list) {
2775			wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2776				    tmp->bss_index);
2777			vif = wcn36xx_priv_to_vif(tmp);
2778			ieee80211_beacon_loss(vif);
2779		}
2780		return 0;
2781	}
2782
2783	if (len != sizeof(*rsp)) {
2784		wcn36xx_warn("Corrupted missed beacon indication\n");
2785		return -EIO;
2786	}
2787
2788	list_for_each_entry(tmp, &wcn->vif_list, list) {
2789		if (tmp->bss_index == rsp->bss_index) {
2790			wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
2791				    rsp->bss_index);
2792			vif = wcn36xx_priv_to_vif(tmp);
2793			ieee80211_beacon_loss(vif);
2794			return 0;
2795		}
2796	}
2797
2798	wcn36xx_warn("BSS index %d not found\n", rsp->bss_index);
2799	return -ENOENT;
2800}
2801
2802static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
2803					      void *buf,
2804					      size_t len)
2805{
2806	struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
2807	struct wcn36xx_vif *vif_priv;
2808	struct ieee80211_vif *vif;
2809	struct ieee80211_bss_conf *bss_conf;
2810	struct ieee80211_sta *sta;
2811	bool found = false;
2812
2813	if (len != sizeof(*rsp)) {
2814		wcn36xx_warn("Corrupted delete sta indication\n");
2815		return -EIO;
2816	}
2817
2818	wcn36xx_dbg(WCN36XX_DBG_HAL,
2819		    "delete station indication %pM index %d reason %d\n",
2820		    rsp->addr2, rsp->sta_id, rsp->reason_code);
2821
2822	list_for_each_entry(vif_priv, &wcn->vif_list, list) {
2823		rcu_read_lock();
2824		vif = wcn36xx_priv_to_vif(vif_priv);
2825
2826		if (vif->type == NL80211_IFTYPE_STATION) {
2827			/* We could call ieee80211_find_sta too, but checking
2828			 * bss_conf is clearer.
2829			 */
2830			bss_conf = &vif->bss_conf;
2831			if (vif_priv->sta_assoc &&
2832			    !memcmp(bss_conf->bssid, rsp->addr2, ETH_ALEN)) {
2833				found = true;
2834				wcn36xx_dbg(WCN36XX_DBG_HAL,
2835					    "connection loss bss_index %d\n",
2836					    vif_priv->bss_index);
2837				ieee80211_connection_loss(vif);
2838			}
2839		} else {
2840			sta = ieee80211_find_sta(vif, rsp->addr2);
2841			if (sta) {
2842				found = true;
2843				ieee80211_report_low_ack(sta, 0);
2844			}
2845		}
2846
2847		rcu_read_unlock();
2848		if (found)
2849			return 0;
2850	}
2851
2852	wcn36xx_warn("BSS or STA with addr %pM not found\n", rsp->addr2);
2853	return -ENOENT;
2854}
2855
2856static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn,
2857					  void *buf,
2858					  size_t len)
2859{
2860	struct wcn36xx_hal_print_reg_info_ind *rsp = buf;
2861	int i;
2862
2863	if (len < sizeof(*rsp)) {
2864		wcn36xx_warn("Corrupted print reg info indication\n");
2865		return -EIO;
2866	}
2867
2868	wcn36xx_dbg(WCN36XX_DBG_HAL,
2869		    "reginfo indication, scenario: 0x%x reason: 0x%x\n",
2870		    rsp->scenario, rsp->reason);
2871
2872	for (i = 0; i < rsp->count; i++) {
2873		wcn36xx_dbg(WCN36XX_DBG_HAL, "\t0x%x: 0x%x\n",
2874			    rsp->regs[i].addr, rsp->regs[i].value);
2875	}
2876
2877	return 0;
2878}
2879
2880int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
2881{
2882	struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
2883	size_t len;
2884	int ret;
2885
2886	mutex_lock(&wcn->hal_mutex);
2887	INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ);
2888
2889	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2890
2891	body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf;
2892	len = msg_body.header.len;
2893
2894	put_cfg_tlv_u32(wcn, &len, cfg_id, value);
2895	body->header.len = len;
2896	body->len = len - sizeof(*body);
2897
2898	ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
2899	if (ret) {
2900		wcn36xx_err("Sending hal_update_cfg failed\n");
2901		goto out;
2902	}
2903	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2904	if (ret) {
2905		wcn36xx_err("hal_update_cfg response failed err=%d\n", ret);
2906		goto out;
2907	}
2908out:
2909	mutex_unlock(&wcn->hal_mutex);
2910	return ret;
2911}
2912
2913int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
2914			    struct ieee80211_vif *vif,
2915			    struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp)
2916{
2917	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2918	struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *msg_body = NULL;
2919	int ret;
2920
2921	mutex_lock(&wcn->hal_mutex);
2922
2923	msg_body = (struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *)
2924		   wcn->hal_buf;
2925	INIT_HAL_MSG(*msg_body, WCN36XX_HAL_8023_MULTICAST_LIST_REQ);
2926
2927	/* An empty list means all mc traffic will be received */
2928	if (fp)
2929		memcpy(&msg_body->mc_addr_list, fp,
2930		       sizeof(msg_body->mc_addr_list));
2931	else
2932		msg_body->mc_addr_list.mc_addr_count = 0;
2933
2934	msg_body->mc_addr_list.bss_index = vif_priv->bss_index;
2935
2936	ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
2937	if (ret) {
2938		wcn36xx_err("Sending HAL_8023_MULTICAST_LIST failed\n");
2939		goto out;
2940	}
2941	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2942	if (ret) {
2943		wcn36xx_err("HAL_8023_MULTICAST_LIST rsp failed err=%d\n", ret);
2944		goto out;
2945	}
2946out:
2947	mutex_unlock(&wcn->hal_mutex);
2948	return ret;
2949}
2950
2951int wcn36xx_smd_arp_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
2952			    bool enable)
2953{
2954	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2955	struct wcn36xx_hal_host_offload_req_msg msg_body;
2956	int ret;
2957
2958	mutex_lock(&wcn->hal_mutex);
2959
2960	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_OFFLOAD_REQ);
2961	msg_body.host_offload_params.offload_type =
2962		WCN36XX_HAL_IPV4_ARP_REPLY_OFFLOAD;
2963	if (enable) {
2964		msg_body.host_offload_params.enable =
2965			WCN36XX_HAL_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
2966		memcpy(&msg_body.host_offload_params.u,
2967		       &vif->cfg.arp_addr_list[0], sizeof(__be32));
2968	}
2969	msg_body.ns_offload_params.bss_index = vif_priv->bss_index;
2970
2971	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
2972
2973	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
2974	if (ret) {
2975		wcn36xx_err("Sending host_offload_arp failed\n");
2976		goto out;
2977	}
2978	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
2979	if (ret) {
2980		wcn36xx_err("host_offload_arp failed err=%d\n", ret);
2981		goto out;
2982	}
2983out:
2984	mutex_unlock(&wcn->hal_mutex);
2985	return ret;
2986}
2987
2988#if IS_ENABLED(CONFIG_IPV6)
2989int wcn36xx_smd_ipv6_ns_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
2990				bool enable)
2991{
2992	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
2993	struct wcn36xx_hal_host_offload_req_msg msg_body;
2994	struct wcn36xx_hal_ns_offload_params *ns_params;
2995	struct wcn36xx_hal_host_offload_req *ho_params;
2996	int ret;
2997
2998	mutex_lock(&wcn->hal_mutex);
2999
3000	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_OFFLOAD_REQ);
3001	ho_params = &msg_body.host_offload_params;
3002	ns_params = &msg_body.ns_offload_params;
3003
3004	ho_params->offload_type = WCN36XX_HAL_IPV6_NS_OFFLOAD;
3005	if (enable) {
3006		ho_params->enable =
3007			WCN36XX_HAL_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE;
3008		if (vif_priv->num_target_ipv6_addrs) {
3009			memcpy(&ho_params->u,
3010			       &vif_priv->target_ipv6_addrs[0].in6_u,
3011			       sizeof(struct in6_addr));
3012			memcpy(&ns_params->target_ipv6_addr1,
3013			       &vif_priv->target_ipv6_addrs[0].in6_u,
3014			       sizeof(struct in6_addr));
3015			ns_params->target_ipv6_addr1_valid = 1;
3016		}
3017		if (vif_priv->num_target_ipv6_addrs > 1) {
3018			memcpy(&ns_params->target_ipv6_addr2,
3019			       &vif_priv->target_ipv6_addrs[1].in6_u,
3020			       sizeof(struct in6_addr));
3021			ns_params->target_ipv6_addr2_valid = 1;
3022		}
3023	}
3024	memcpy(&ns_params->self_addr, vif->addr, ETH_ALEN);
3025	ns_params->bss_index = vif_priv->bss_index;
3026
3027	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3028
3029	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3030	if (ret) {
3031		wcn36xx_err("Sending host_offload_arp failed\n");
3032		goto out;
3033	}
3034	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3035	if (ret) {
3036		wcn36xx_err("host_offload_arp failed err=%d\n", ret);
3037		goto out;
3038	}
3039out:
3040	mutex_unlock(&wcn->hal_mutex);
3041	return ret;
3042}
3043#else
3044int wcn36xx_smd_ipv6_ns_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
3045				bool enable)
3046{
3047	return 0;
3048}
3049#endif
3050
3051int wcn36xx_smd_gtk_offload(struct wcn36xx *wcn, struct ieee80211_vif *vif,
3052			    bool enable)
3053{
3054	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3055	struct wcn36xx_hal_gtk_offload_req_msg msg_body;
3056	int ret;
3057
3058	mutex_lock(&wcn->hal_mutex);
3059
3060	INIT_HAL_MSG(msg_body, WCN36XX_HAL_GTK_OFFLOAD_REQ);
3061
3062	if (enable) {
3063		memcpy(&msg_body.kek, vif_priv->rekey_data.kek, NL80211_KEK_LEN);
3064		memcpy(&msg_body.kck, vif_priv->rekey_data.kck, NL80211_KCK_LEN);
3065		msg_body.key_replay_counter =
3066			le64_to_cpu(vif_priv->rekey_data.replay_ctr);
3067		msg_body.bss_index = vif_priv->bss_index;
3068	} else {
3069		msg_body.flags = WCN36XX_HAL_GTK_OFFLOAD_FLAGS_DISABLE;
3070	}
3071
3072	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3073
3074	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3075	if (ret) {
3076		wcn36xx_err("Sending host_offload_arp failed\n");
3077		goto out;
3078	}
3079	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3080	if (ret) {
3081		wcn36xx_err("host_offload_arp failed err=%d\n", ret);
3082		goto out;
3083	}
3084out:
3085	mutex_unlock(&wcn->hal_mutex);
3086	return ret;
3087}
3088
3089static int wcn36xx_smd_gtk_offload_get_info_rsp(struct wcn36xx *wcn,
3090						struct ieee80211_vif *vif)
3091{
3092	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3093	struct wcn36xx_hal_gtk_offload_get_info_rsp_msg *rsp;
3094	__be64 replay_ctr;
3095
3096	if (wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len))
3097		return -EIO;
3098
3099	rsp = (struct wcn36xx_hal_gtk_offload_get_info_rsp_msg *)wcn->hal_buf;
3100
3101	if (rsp->bss_index != vif_priv->bss_index) {
3102		wcn36xx_err("gtk_offload_info invalid response bss index %d\n",
3103			    rsp->bss_index);
3104		return -ENOENT;
3105	}
3106
3107	if (vif_priv->rekey_data.replay_ctr != cpu_to_le64(rsp->key_replay_counter)) {
3108		replay_ctr = cpu_to_be64(rsp->key_replay_counter);
3109		vif_priv->rekey_data.replay_ctr =
3110			cpu_to_le64(rsp->key_replay_counter);
3111		ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
3112					   (void *)&replay_ctr, GFP_KERNEL);
3113		wcn36xx_dbg(WCN36XX_DBG_HAL,
3114			    "GTK replay counter increment %llu\n",
3115			    rsp->key_replay_counter);
3116	}
3117
3118	wcn36xx_dbg(WCN36XX_DBG_HAL,
3119		    "gtk offload info status %d last_rekey_status %d "
3120		    "replay_counter %llu total_rekey_count %d gtk_rekey_count %d "
3121		    "igtk_rekey_count %d bss_index %d\n",
3122		    rsp->status, rsp->last_rekey_status,
3123		    rsp->key_replay_counter, rsp->total_rekey_count,
3124		    rsp->gtk_rekey_count, rsp->igtk_rekey_count,
3125		    rsp->bss_index);
3126
3127	return 0;
3128}
3129
3130int wcn36xx_smd_gtk_offload_get_info(struct wcn36xx *wcn,
3131				     struct ieee80211_vif *vif)
3132{
3133	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3134	struct wcn36xx_hal_gtk_offload_get_info_req_msg msg_body;
3135	int ret;
3136
3137	mutex_lock(&wcn->hal_mutex);
3138
3139	INIT_HAL_MSG(msg_body, WCN36XX_HAL_GTK_OFFLOAD_GETINFO_REQ);
3140
3141	msg_body.bss_index = vif_priv->bss_index;
3142
3143	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3144
3145	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3146	if (ret) {
3147		wcn36xx_err("Sending gtk_offload_get_info failed\n");
3148		goto out;
3149	}
3150	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3151	if (ret) {
3152		wcn36xx_err("gtk_offload_get_info failed err=%d\n", ret);
3153		goto out;
3154	}
3155	ret = wcn36xx_smd_gtk_offload_get_info_rsp(wcn, vif);
3156out:
3157	mutex_unlock(&wcn->hal_mutex);
3158	return ret;
3159}
3160
3161int wcn36xx_smd_wlan_host_suspend_ind(struct wcn36xx *wcn)
3162{
3163	struct wcn36xx_hal_wlan_host_suspend_ind_msg msg_body;
3164	int ret;
3165
3166	mutex_lock(&wcn->hal_mutex);
3167
3168	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_SUSPEND_IND);
3169	msg_body.configured_mcst_bcst_filter_setting = 0;
3170	msg_body.active_session_count = 1;
3171	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3172
3173	ret = rpmsg_send(wcn->smd_channel, wcn->hal_buf, msg_body.header.len);
3174
3175	mutex_unlock(&wcn->hal_mutex);
3176
3177	return ret;
3178}
3179
3180int wcn36xx_smd_host_resume(struct wcn36xx *wcn)
3181{
3182	struct wcn36xx_hal_wlan_host_resume_req_msg msg_body;
3183	struct wcn36xx_hal_host_resume_rsp_msg *rsp;
3184	int ret;
3185
3186	mutex_lock(&wcn->hal_mutex);
3187
3188	INIT_HAL_MSG(msg_body, WCN36XX_HAL_HOST_RESUME_REQ);
3189	msg_body.configured_mcst_bcst_filter_setting = 0;
3190
3191	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3192
3193	ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
3194	if (ret) {
3195		wcn36xx_err("Sending wlan_host_resume failed\n");
3196		goto out;
3197	}
3198	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3199	if (ret) {
3200		wcn36xx_err("wlan_host_resume err=%d\n", ret);
3201		goto out;
3202	}
3203
3204	rsp = (struct wcn36xx_hal_host_resume_rsp_msg *)wcn->hal_buf;
3205	if (rsp->status)
3206		wcn36xx_warn("wlan_host_resume status=%d\n", rsp->status);
3207
3208out:
3209	mutex_unlock(&wcn->hal_mutex);
3210
3211	return ret;
3212}
3213
3214#define BEACON_FILTER(eid, presence, offs, val, mask, ref_val) \
3215	{					\
3216		.element_id = eid,		\
3217		.check_ie_presence = presence,	\
3218		.offset = offs,			\
3219		.value = val,			\
3220		.bitmask = mask,		\
3221		.ref = ref_val,			\
3222	}
3223
3224static const struct beacon_filter_ie bcn_filter_ies[] = {
3225	BEACON_FILTER(WLAN_EID_DS_PARAMS, 0, 0, 0,
3226		      WCN36XX_FILTER_IE_DS_CHANNEL_MASK, 0),
3227	BEACON_FILTER(WLAN_EID_ERP_INFO, 0, 0, 0,
3228		      WCN36XX_FILTER_IE_ERP_FILTER_MASK, 0),
3229	BEACON_FILTER(WLAN_EID_EDCA_PARAM_SET, 0, 0, 0,
3230		      WCN36XX_FILTER_IE_EDCA_FILTER_MASK, 0),
3231	BEACON_FILTER(WLAN_EID_QOS_CAPA, 0, 0, 0,
3232		      WCN36XX_FILTER_IE_QOS_FILTER_MASK, 0),
3233	BEACON_FILTER(WLAN_EID_CHANNEL_SWITCH, 1, 0, 0,
3234		      WCN36XX_FILTER_IE_CHANNEL_SWITCH_MASK, 0),
3235	BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 0, 0,
3236		      WCN36XX_FILTER_IE_HT_BYTE0_FILTER_MASK, 0),
3237	BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 2, 0,
3238		      WCN36XX_FILTER_IE_HT_BYTE2_FILTER_MASK, 0),
3239	BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 5, 0,
3240		      WCN36XX_FILTER_IE_HT_BYTE5_FILTER_MASK, 0),
3241	BEACON_FILTER(WLAN_EID_PWR_CONSTRAINT, 0, 0, 0,
3242		      WCN36XX_FILTER_IE_PWR_CONSTRAINT_MASK, 0),
3243	BEACON_FILTER(WLAN_EID_OPMODE_NOTIF, 0, 0, 0,
3244		      WCN36XX_FILTER_IE_OPMODE_NOTIF_MASK, 0),
3245	BEACON_FILTER(WLAN_EID_VHT_OPERATION, 0, 0, 0,
3246		      WCN36XX_FILTER_IE_VHTOP_CHWIDTH_MASK, 0),
3247	BEACON_FILTER(WLAN_EID_RSN, 1, 0, 0,
3248		      WCN36XX_FILTER_IE_RSN_MASK, 0),
3249	BEACON_FILTER(WLAN_EID_VENDOR_SPECIFIC, 1, 0, 0,
3250		      WCN36XX_FILTER_IE_VENDOR_MASK, 0),
3251};
3252
3253int wcn36xx_smd_add_beacon_filter(struct wcn36xx *wcn,
3254				  struct ieee80211_vif *vif)
3255{
3256	struct wcn36xx_hal_add_bcn_filter_req_msg msg_body, *body;
3257	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
3258	u8 *payload;
3259	size_t payload_size;
3260	int ret;
3261
3262	if (!wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, BCN_FILTER))
3263		return -EOPNOTSUPP;
3264
3265	mutex_lock(&wcn->hal_mutex);
3266	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BCN_FILTER_REQ);
3267
3268	PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
3269
3270	body = (struct wcn36xx_hal_add_bcn_filter_req_msg *)wcn->hal_buf;
3271	body->capability_info = vif->bss_conf.assoc_capability;
3272	body->capability_mask = WCN36XX_FILTER_CAPABILITY_MASK;
3273	body->beacon_interval = vif->bss_conf.beacon_int;
3274	body->ie_num = ARRAY_SIZE(bcn_filter_ies);
3275	body->bss_index = vif_priv->bss_index;
3276
3277	payload = ((u8 *)body) + body->header.len;
3278	payload_size = sizeof(bcn_filter_ies);
3279	memcpy(payload, &bcn_filter_ies, payload_size);
3280
3281	body->header.len += payload_size;
3282
3283	ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
3284	if (ret) {
3285		wcn36xx_err("Sending add bcn_filter failed\n");
3286		goto out;
3287	}
3288
3289	ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
3290	if (ret) {
3291		wcn36xx_err("add bcn filter response failed err=%d\n", ret);
3292		goto out;
3293	}
3294out:
3295	mutex_unlock(&wcn->hal_mutex);
3296	return ret;
3297}
3298
3299int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
3300			    void *buf, int len, void *priv, u32 addr)
3301{
3302	const struct wcn36xx_hal_msg_header *msg_header = buf;
3303	struct ieee80211_hw *hw = priv;
3304	struct wcn36xx *wcn = hw->priv;
3305	struct wcn36xx_hal_ind_msg *msg_ind;
3306	wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
3307
3308	switch (msg_header->msg_type) {
3309	case WCN36XX_HAL_START_RSP:
3310	case WCN36XX_HAL_CONFIG_STA_RSP:
3311	case WCN36XX_HAL_CONFIG_BSS_RSP:
3312	case WCN36XX_HAL_ADD_STA_SELF_RSP:
3313	case WCN36XX_HAL_STOP_RSP:
3314	case WCN36XX_HAL_DEL_STA_SELF_RSP:
3315	case WCN36XX_HAL_DELETE_STA_RSP:
3316	case WCN36XX_HAL_INIT_SCAN_RSP:
3317	case WCN36XX_HAL_START_SCAN_RSP:
3318	case WCN36XX_HAL_END_SCAN_RSP:
3319	case WCN36XX_HAL_FINISH_SCAN_RSP:
3320	case WCN36XX_HAL_DOWNLOAD_NV_RSP:
3321	case WCN36XX_HAL_DELETE_BSS_RSP:
3322	case WCN36XX_HAL_SEND_BEACON_RSP:
3323	case WCN36XX_HAL_SET_LINK_ST_RSP:
3324	case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP:
3325	case WCN36XX_HAL_SET_BSSKEY_RSP:
3326	case WCN36XX_HAL_SET_STAKEY_RSP:
3327	case WCN36XX_HAL_RMV_STAKEY_RSP:
3328	case WCN36XX_HAL_RMV_BSSKEY_RSP:
3329	case WCN36XX_HAL_ENTER_BMPS_RSP:
3330	case WCN36XX_HAL_SET_POWER_PARAMS_RSP:
3331	case WCN36XX_HAL_EXIT_BMPS_RSP:
3332	case WCN36XX_HAL_KEEP_ALIVE_RSP:
3333	case WCN36XX_HAL_DUMP_COMMAND_RSP:
3334	case WCN36XX_HAL_ADD_BA_SESSION_RSP:
3335	case WCN36XX_HAL_ADD_BA_RSP:
3336	case WCN36XX_HAL_DEL_BA_RSP:
3337	case WCN36XX_HAL_GET_STATS_RSP:
3338	case WCN36XX_HAL_TRIGGER_BA_RSP:
3339	case WCN36XX_HAL_UPDATE_CFG_RSP:
3340	case WCN36XX_HAL_JOIN_RSP:
3341	case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP:
3342	case WCN36XX_HAL_CH_SWITCH_RSP:
3343	case WCN36XX_HAL_PROCESS_PTT_RSP:
3344	case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
3345	case WCN36XX_HAL_8023_MULTICAST_LIST_RSP:
3346	case WCN36XX_HAL_START_SCAN_OFFLOAD_RSP:
3347	case WCN36XX_HAL_STOP_SCAN_OFFLOAD_RSP:
3348	case WCN36XX_HAL_HOST_OFFLOAD_RSP:
3349	case WCN36XX_HAL_GTK_OFFLOAD_RSP:
3350	case WCN36XX_HAL_GTK_OFFLOAD_GETINFO_RSP:
3351	case WCN36XX_HAL_HOST_RESUME_RSP:
3352	case WCN36XX_HAL_ENTER_IMPS_RSP:
3353	case WCN36XX_HAL_EXIT_IMPS_RSP:
3354	case WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP:
3355	case WCN36XX_HAL_ADD_BCN_FILTER_RSP:
3356		memcpy(wcn->hal_buf, buf, len);
3357		wcn->hal_rsp_len = len;
3358		complete(&wcn->hal_rsp_compl);
3359		break;
3360
3361	case WCN36XX_HAL_COEX_IND:
3362	case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
3363	case WCN36XX_HAL_DEL_BA_IND:
3364	case WCN36XX_HAL_OTA_TX_COMPL_IND:
3365	case WCN36XX_HAL_MISSED_BEACON_IND:
3366	case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
3367	case WCN36XX_HAL_PRINT_REG_INFO_IND:
3368	case WCN36XX_HAL_SCAN_OFFLOAD_IND:
3369		msg_ind = kmalloc(struct_size(msg_ind, msg, len), GFP_ATOMIC);
3370		if (!msg_ind) {
3371			wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
3372				    msg_header->msg_type);
3373			return -ENOMEM;
3374		}
3375
3376		msg_ind->msg_len = len;
3377		memcpy(msg_ind->msg, buf, len);
3378
3379		spin_lock(&wcn->hal_ind_lock);
3380		list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
3381		queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
3382		spin_unlock(&wcn->hal_ind_lock);
3383		wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
3384		break;
3385	default:
3386		wcn36xx_err("SMD_EVENT (%d) not supported\n",
3387			      msg_header->msg_type);
3388	}
3389
3390	return 0;
3391}
3392
3393static void wcn36xx_ind_smd_work(struct work_struct *work)
3394{
3395	struct wcn36xx *wcn =
3396		container_of(work, struct wcn36xx, hal_ind_work);
3397
3398	for (;;) {
3399		struct wcn36xx_hal_msg_header *msg_header;
3400		struct wcn36xx_hal_ind_msg *hal_ind_msg;
3401		unsigned long flags;
3402
3403		spin_lock_irqsave(&wcn->hal_ind_lock, flags);
3404
3405		if (list_empty(&wcn->hal_ind_queue)) {
3406			spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
3407			return;
3408		}
3409
3410		hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
3411					       struct wcn36xx_hal_ind_msg,
3412					       list);
3413		list_del(&hal_ind_msg->list);
3414		spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
3415
3416		msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
3417
3418		switch (msg_header->msg_type) {
3419		case WCN36XX_HAL_COEX_IND:
3420		case WCN36XX_HAL_DEL_BA_IND:
3421		case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
3422			break;
3423		case WCN36XX_HAL_OTA_TX_COMPL_IND:
3424			wcn36xx_smd_tx_compl_ind(wcn,
3425						 hal_ind_msg->msg,
3426						 hal_ind_msg->msg_len);
3427			break;
3428		case WCN36XX_HAL_MISSED_BEACON_IND:
3429			wcn36xx_smd_missed_beacon_ind(wcn,
3430						      hal_ind_msg->msg,
3431						      hal_ind_msg->msg_len);
3432			break;
3433		case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
3434			wcn36xx_smd_delete_sta_context_ind(wcn,
3435							   hal_ind_msg->msg,
3436							   hal_ind_msg->msg_len);
3437			break;
3438		case WCN36XX_HAL_PRINT_REG_INFO_IND:
3439			wcn36xx_smd_print_reg_info_ind(wcn,
3440						       hal_ind_msg->msg,
3441						       hal_ind_msg->msg_len);
3442			break;
3443		case WCN36XX_HAL_SCAN_OFFLOAD_IND:
3444			wcn36xx_smd_hw_scan_ind(wcn, hal_ind_msg->msg,
3445						hal_ind_msg->msg_len);
3446			break;
3447		default:
3448			wcn36xx_err("SMD_EVENT (%d) not supported\n",
3449				    msg_header->msg_type);
3450		}
3451
3452		kfree(hal_ind_msg);
3453	}
3454}
3455
3456int wcn36xx_smd_open(struct wcn36xx *wcn)
3457{
3458	wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind");
3459	if (!wcn->hal_ind_wq)
3460		return -ENOMEM;
3461
3462	INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
3463	INIT_LIST_HEAD(&wcn->hal_ind_queue);
3464	spin_lock_init(&wcn->hal_ind_lock);
3465
3466	return 0;
3467}
3468
3469void wcn36xx_smd_close(struct wcn36xx *wcn)
3470{
3471	struct wcn36xx_hal_ind_msg *msg, *tmp;
3472
3473	cancel_work_sync(&wcn->hal_ind_work);
3474	destroy_workqueue(wcn->hal_ind_wq);
3475
3476	list_for_each_entry_safe(msg, tmp, &wcn->hal_ind_queue, list)
3477		kfree(msg);
3478}
3479