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