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