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