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