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