2 * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
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.
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.
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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>
27 struct wcn36xx_cfg_val
{
32 #define WCN36XX_CFG_VAL(id, val) \
34 .cfg_id = WCN36XX_HAL_CFG_ ## id, \
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),
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),
182 static int put_cfg_tlv_u32(struct wcn36xx
*wcn
, size_t *len
, u32 id
, u32 value
)
184 struct wcn36xx_hal_cfg
*entry
;
187 if (*len
+ sizeof(*entry
) + sizeof(u32
) >= WCN36XX_HAL_BUF_SIZE
) {
188 wcn36xx_err("Not enough room for TLV entry\n");
192 entry
= (struct wcn36xx_hal_cfg
*) (wcn
->hal_buf
+ *len
);
194 entry
->len
= sizeof(u32
);
195 entry
->pad_bytes
= 0;
198 val
= (u32
*) (entry
+ 1);
201 *len
+= sizeof(*entry
) + sizeof(u32
);
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
)
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
;
217 bss_params
->nw_type
= WCN36XX_HAL_11B_NW_TYPE
;
220 static inline u8
is_cap_supported(unsigned long caps
, unsigned long flag
)
222 return caps
& flag
? 1 : 0;
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
)
229 if (sta
&& sta
->deflink
.ht_cap
.ht_supported
) {
230 unsigned long caps
= sta
->deflink
.ht_cap
.cap
;
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
);
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;
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
)
255 if (sta
&& sta
->deflink
.vht_cap
.vht_supported
)
256 bss
->vht_capable
= 1;
259 static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta
*sta
,
260 struct wcn36xx_hal_config_sta_params
*sta_params
)
262 if (sta
->deflink
.ht_cap
.ht_supported
) {
263 unsigned long caps
= sta
->deflink
.ht_cap
.cap
;
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
);
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
);
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
)
293 if (sta
->deflink
.vht_cap
.vht_supported
) {
294 unsigned long caps
= sta
->deflink
.vht_cap
.cap
;
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;
305 sta_params
->vht_tx_mu_beamformee_capable
= 0;
307 sta_params
->vht_tx_channel_width_set
= 0;
311 static void wcn36xx_smd_set_sta_ht_ldpc_params(struct ieee80211_sta
*sta
,
312 struct wcn36xx_hal_config_sta_params_v1
*sta_params
)
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
);
321 static void wcn36xx_smd_set_sta_default_ht_params(
322 struct wcn36xx_hal_config_sta_params
*sta_params
)
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;
337 static void wcn36xx_smd_set_sta_default_vht_params(struct wcn36xx
*wcn
,
338 struct wcn36xx_hal_config_sta_params_v1
*sta_params
)
340 if (wcn
->rf_id
== RF_IRIS_WCN3680
) {
341 sta_params
->vht_capable
= 1;
342 sta_params
->vht_tx_mu_beamformee_capable
= 1;
344 sta_params
->vht_capable
= 0;
345 sta_params
->vht_tx_mu_beamformee_capable
= 0;
348 sta_params
->vht_ldpc_enabled
= 0;
349 sta_params
->vht_tx_channel_width_set
= 0;
350 sta_params
->vht_tx_bf_enabled
= 0;
353 static void wcn36xx_smd_set_sta_default_ht_ldpc_params(struct wcn36xx
*wcn
,
354 struct wcn36xx_hal_config_sta_params_v1
*sta_params
)
356 if (wcn
->rf_id
== RF_IRIS_WCN3680
)
357 sta_params
->ht_ldpc_enabled
= 1;
359 sta_params
->ht_ldpc_enabled
= 0;
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
)
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
;
375 sta_params
->type
= 0;
376 sta_params
->sta_index
= vif_priv
->self_sta_index
;
379 sta_params
->listen_interval
= WCN36XX_LISTEN_INTERVAL(wcn
);
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.
386 if (NL80211_IFTYPE_STATION
== vif
->type
)
387 memcpy(&sta_params
->mac
, vif
->addr
, ETH_ALEN
);
389 memcpy(&sta_params
->bssid
, vif
->addr
, ETH_ALEN
);
391 sta_params
->encrypt_type
= vif_priv
->encrypt_type
;
392 sta_params
->short_preamble_supported
= true;
394 sta_params
->rifs_mode
= 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
;
404 sta_priv
= wcn36xx_sta_to_priv(sta
);
405 if (NL80211_IFTYPE_STATION
== vif
->type
)
406 memcpy(&sta_params
->bssid
, sta
->addr
, ETH_ALEN
);
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
));
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
);
422 static int wcn36xx_smd_send_and_wait(struct wcn36xx
*wcn
, size_t len
)
426 struct wcn36xx_hal_msg_header
*hdr
=
427 (struct wcn36xx_hal_msg_header
*)wcn
->hal_buf
;
428 u16 req_type
= hdr
->msg_type
;
430 wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP
, "HAL >>> ", wcn
->hal_buf
, len
);
432 init_completion(&wcn
->hal_rsp_compl
);
434 ret
= rpmsg_send(wcn
->smd_channel
, wcn
->hal_buf
, len
);
436 wcn36xx_err("HAL TX failed for req %d\n", req_type
);
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
);
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
));
454 #define __INIT_HAL_MSG(msg_body, type, version) \
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); \
462 #define INIT_HAL_MSG(msg_body, type) \
463 __INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION0)
465 #define INIT_HAL_MSG_V1(msg_body, type) \
466 __INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION1)
468 #define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \
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; \
476 #define PREPARE_HAL_BUF(send_buf, msg_body) \
478 memcpy_and_pad(send_buf, msg_body.header.len, \
479 &msg_body, sizeof(msg_body), 0); \
482 #define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \
484 memcpy(send_buf, p_msg_body, p_msg_body->header.len); \
487 static int wcn36xx_smd_rsp_status_check(void *buf
, size_t len
)
489 struct wcn36xx_fw_msg_status_rsp
*rsp
;
491 if (len
< sizeof(struct wcn36xx_hal_msg_header
) +
492 sizeof(struct wcn36xx_fw_msg_status_rsp
))
495 rsp
= (struct wcn36xx_fw_msg_status_rsp
*)
496 (buf
+ sizeof(struct wcn36xx_hal_msg_header
));
498 if (WCN36XX_FW_MSG_RESULT_SUCCESS
!= rsp
->status
)
504 int wcn36xx_smd_load_nv(struct wcn36xx
*wcn
)
506 struct nv_data
*nv_d
;
507 struct wcn36xx_hal_nv_img_download_req_msg msg_body
;
513 ret
= request_firmware(&wcn
->nv
, wcn
->nv_file
, wcn
->dev
);
515 wcn36xx_err("Failed to load nv file %s: %d\n",
521 nv_d
= (struct nv_data
*)wcn
->nv
->data
;
522 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_DOWNLOAD_NV_REQ
);
524 msg_body
.header
.len
+= WCN36XX_NV_FRAGMENT_SIZE
;
526 msg_body
.frag_number
= 0;
527 /* hal_buf must be protected with mutex */
528 mutex_lock(&wcn
->hal_mutex
);
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
;
536 msg_body
.last_fragment
= 1;
537 msg_body
.nv_img_buffer_size
= fw_bytes_left
;
539 /* Do not forget update general message len */
540 msg_body
.header
.len
= sizeof(msg_body
) + fw_bytes_left
;
544 /* Add load NV request message header */
545 memcpy(wcn
->hal_buf
, &msg_body
, sizeof(msg_body
));
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
);
552 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
555 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
,
558 wcn36xx_err("hal_load_nv response failed err=%d\n",
562 msg_body
.frag_number
++;
563 fm_offset
+= WCN36XX_NV_FRAGMENT_SIZE
;
565 } while (msg_body
.last_fragment
!= 1);
568 mutex_unlock(&wcn
->hal_mutex
);
572 static int wcn36xx_smd_start_rsp(struct wcn36xx
*wcn
, void *buf
, size_t len
)
574 struct wcn36xx_hal_mac_start_rsp_msg
*rsp
;
576 if (len
< sizeof(*rsp
))
581 if (WCN36XX_FW_MSG_RESULT_SUCCESS
!= rsp
->start_rsp_params
.status
)
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
);
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';
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
;
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
);
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
);
612 int wcn36xx_smd_start(struct wcn36xx
*wcn
)
614 struct wcn36xx_hal_mac_start_req_msg msg_body
, *body
;
619 static struct wcn36xx_cfg_val
*cfg_vals
;
621 mutex_lock(&wcn
->hal_mutex
);
622 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_START_REQ
);
624 msg_body
.params
.type
= DRIVER_TYPE_PRODUCTION
;
625 msg_body
.params
.len
= 0;
627 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
629 body
= (struct wcn36xx_hal_mac_start_req_msg
*)wcn
->hal_buf
;
630 len
= body
->header
.len
;
632 if (wcn
->rf_id
== RF_IRIS_WCN3680
) {
633 cfg_vals
= wcn3680_cfg_vals
;
634 cfg_elements
= ARRAY_SIZE(wcn3680_cfg_vals
);
636 cfg_vals
= wcn36xx_cfg_vals
;
637 cfg_elements
= ARRAY_SIZE(wcn36xx_cfg_vals
);
640 for (i
= 0; i
< cfg_elements
; i
++) {
641 ret
= put_cfg_tlv_u32(wcn
, &len
, cfg_vals
[i
].cfg_id
,
646 body
->header
.len
= len
;
647 body
->params
.len
= len
- sizeof(*body
);
649 wcn36xx_dbg(WCN36XX_DBG_HAL
, "hal start type %d\n",
650 msg_body
.params
.type
);
652 ret
= wcn36xx_smd_send_and_wait(wcn
, body
->header
.len
);
654 wcn36xx_err("Sending hal_start failed\n");
658 ret
= wcn36xx_smd_start_rsp(wcn
, wcn
->hal_buf
, wcn
->hal_rsp_len
);
660 wcn36xx_err("hal_start response failed err=%d\n", ret
);
665 mutex_unlock(&wcn
->hal_mutex
);
669 int wcn36xx_smd_stop(struct wcn36xx
*wcn
)
671 struct wcn36xx_hal_mac_stop_req_msg msg_body
;
674 mutex_lock(&wcn
->hal_mutex
);
675 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_STOP_REQ
);
677 msg_body
.stop_req_params
.reason
= HAL_STOP_TYPE_RF_KILL
;
679 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
681 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
683 wcn36xx_err("Sending hal_stop failed\n");
686 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
688 wcn36xx_err("hal_stop response failed err=%d\n", ret
);
692 mutex_unlock(&wcn
->hal_mutex
);
696 int wcn36xx_smd_init_scan(struct wcn36xx
*wcn
, enum wcn36xx_hal_sys_mode mode
,
697 struct ieee80211_vif
*vif
)
699 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
700 struct wcn36xx_hal_init_scan_req_msg msg_body
;
703 mutex_lock(&wcn
->hal_mutex
);
704 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_INIT_SCAN_REQ
);
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;
711 msg_body
.scan_entry
.bss_index
[0] = vif_priv
->bss_index
;
712 msg_body
.scan_entry
.active_bss_count
= 1;
715 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
717 wcn36xx_dbg(WCN36XX_DBG_HAL
, "hal init scan mode %d\n", msg_body
.mode
);
719 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
721 wcn36xx_err("Sending hal_init_scan failed\n");
724 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
726 wcn36xx_err("hal_init_scan response failed err=%d\n", ret
);
729 wcn
->sw_scan_init
= true;
731 mutex_unlock(&wcn
->hal_mutex
);
735 int wcn36xx_smd_start_scan(struct wcn36xx
*wcn
, u8 scan_channel
)
737 struct wcn36xx_hal_start_scan_req_msg msg_body
;
740 mutex_lock(&wcn
->hal_mutex
);
741 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_START_SCAN_REQ
);
743 msg_body
.scan_channel
= scan_channel
;
745 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
747 wcn36xx_dbg(WCN36XX_DBG_HAL
, "hal start scan channel %d\n",
748 msg_body
.scan_channel
);
750 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
752 wcn36xx_err("Sending hal_start_scan failed\n");
755 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
757 wcn36xx_err("hal_start_scan response failed err=%d\n", ret
);
760 wcn
->sw_scan_channel
= scan_channel
;
762 mutex_unlock(&wcn
->hal_mutex
);
766 int wcn36xx_smd_end_scan(struct wcn36xx
*wcn
, u8 scan_channel
)
768 struct wcn36xx_hal_end_scan_req_msg msg_body
;
771 mutex_lock(&wcn
->hal_mutex
);
772 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_END_SCAN_REQ
);
774 msg_body
.scan_channel
= scan_channel
;
776 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
778 wcn36xx_dbg(WCN36XX_DBG_HAL
, "hal end scan channel %d\n",
779 msg_body
.scan_channel
);
781 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
783 wcn36xx_err("Sending hal_end_scan failed\n");
786 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
788 wcn36xx_err("hal_end_scan response failed err=%d\n", ret
);
791 wcn
->sw_scan_channel
= 0;
793 mutex_unlock(&wcn
->hal_mutex
);
797 int wcn36xx_smd_finish_scan(struct wcn36xx
*wcn
,
798 enum wcn36xx_hal_sys_mode mode
,
799 struct ieee80211_vif
*vif
)
801 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
802 struct wcn36xx_hal_finish_scan_req_msg msg_body
;
805 mutex_lock(&wcn
->hal_mutex
);
806 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_FINISH_SCAN_REQ
);
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 */
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;
818 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
820 wcn36xx_dbg(WCN36XX_DBG_HAL
, "hal finish scan mode %d\n",
823 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
825 wcn36xx_err("Sending hal_finish_scan failed\n");
828 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
830 wcn36xx_err("hal_finish_scan response failed err=%d\n", ret
);
833 wcn
->sw_scan_init
= false;
835 mutex_unlock(&wcn
->hal_mutex
);
839 int wcn36xx_smd_start_hw_scan(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
,
840 struct cfg80211_scan_request
*req
)
842 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
843 struct wcn36xx_hal_start_scan_offload_req_msg
*msg_body
;
846 if (req
->ie_len
> WCN36XX_MAX_SCAN_IE_LEN
)
849 mutex_lock(&wcn
->hal_mutex
);
850 msg_body
= kzalloc(sizeof(*msg_body
), GFP_KERNEL
);
856 INIT_HAL_MSG((*msg_body
), WCN36XX_HAL_START_SCAN_OFFLOAD_REQ
);
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
;
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
);
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
);
881 msg_body
->header
.len
-= WCN36XX_MAX_SCAN_IE_LEN
;
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
);
889 PREPARE_HAL_BUF(wcn
->hal_buf
, (*msg_body
));
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");
896 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
->header
.len
);
898 wcn36xx_err("Sending hal_start_scan_offload failed\n");
901 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
903 wcn36xx_err("hal_start_scan_offload response failed err=%d\n",
909 mutex_unlock(&wcn
->hal_mutex
);
913 int wcn36xx_smd_stop_hw_scan(struct wcn36xx
*wcn
)
915 struct wcn36xx_hal_stop_scan_offload_req_msg msg_body
;
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
);
922 wcn36xx_dbg(WCN36XX_DBG_HAL
, "hal stop hw-scan\n");
924 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
926 wcn36xx_err("Sending hal_stop_scan_offload failed\n");
929 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
931 wcn36xx_err("hal_stop_scan_offload response failed err=%d\n",
936 mutex_unlock(&wcn
->hal_mutex
);
940 int wcn36xx_smd_update_channel_list(struct wcn36xx
*wcn
, struct cfg80211_scan_request
*req
)
942 struct wcn36xx_hal_update_channel_list_req_msg
*msg_body
;
945 msg_body
= kzalloc(sizeof(*msg_body
), GFP_KERNEL
);
949 INIT_HAL_MSG((*msg_body
), WCN36XX_HAL_UPDATE_CHANNEL_LIST_REQ
);
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
;
957 param
->mhz
= req
->channels
[i
]->center_freq
;
958 param
->band_center_freq1
= req
->channels
[i
]->center_freq
;
959 param
->band_center_freq2
= 0;
961 if (req
->channels
[i
]->flags
& IEEE80211_CHAN_NO_IR
)
962 param
->channel_info
|= WCN36XX_HAL_CHAN_INFO_FLAG_PASSIVE
;
964 if (req
->channels
[i
]->flags
& IEEE80211_CHAN_RADAR
)
965 param
->channel_info
|= WCN36XX_HAL_CHAN_INFO_FLAG_DFS
;
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
;
972 param
->channel_info
|= WCN36XX_HAL_CHAN_INFO_PHY_11BG
;
975 if (min_power
> req
->channels
[i
]->max_power
)
976 min_power
= req
->channels
[i
]->max_power
;
978 if (req
->channels
[i
]->max_antenna_gain
)
979 ant_gain
= req
->channels
[i
]->max_antenna_gain
;
981 u32p_replace_bits(¶m
->reg_info_1
, min_power
,
982 WCN36XX_HAL_CHAN_REG1_MIN_PWR_MASK
);
983 u32p_replace_bits(¶m
->reg_info_1
, req
->channels
[i
]->max_power
,
984 WCN36XX_HAL_CHAN_REG1_MAX_PWR_MASK
);
985 u32p_replace_bits(¶m
->reg_info_1
, req
->channels
[i
]->max_reg_power
,
986 WCN36XX_HAL_CHAN_REG1_REG_PWR_MASK
);
987 u32p_replace_bits(¶m
->reg_info_1
, 0,
988 WCN36XX_HAL_CHAN_REG1_CLASS_ID_MASK
);
989 u32p_replace_bits(¶m
->reg_info_2
, ant_gain
,
990 WCN36XX_HAL_CHAN_REG2_ANT_GAIN_MASK
);
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
,
998 mutex_lock(&wcn
->hal_mutex
);
1000 PREPARE_HAL_BUF(wcn
->hal_buf
, (*msg_body
));
1002 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
->header
.len
);
1004 wcn36xx_err("Sending hal_update_channel_list failed\n");
1008 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
1010 wcn36xx_err("hal_update_channel_list response failed err=%d\n", ret
);
1016 mutex_unlock(&wcn
->hal_mutex
);
1020 static int wcn36xx_smd_switch_channel_rsp(void *buf
, size_t len
)
1022 struct wcn36xx_hal_switch_channel_rsp_msg
*rsp
;
1025 ret
= wcn36xx_smd_rsp_status_check(buf
, len
);
1029 wcn36xx_dbg(WCN36XX_DBG_HAL
, "channel switched to: %d, status: %d\n",
1030 rsp
->channel_number
, rsp
->status
);
1034 int wcn36xx_smd_switch_channel(struct wcn36xx
*wcn
,
1035 struct ieee80211_vif
*vif
, int ch
)
1037 struct wcn36xx_hal_switch_channel_req_msg msg_body
;
1040 mutex_lock(&wcn
->hal_mutex
);
1041 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_CH_SWITCH_REQ
);
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
);
1048 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
1050 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1052 wcn36xx_err("Sending hal_switch_channel failed\n");
1055 ret
= wcn36xx_smd_switch_channel_rsp(wcn
->hal_buf
, wcn
->hal_rsp_len
);
1057 wcn36xx_err("hal_switch_channel response failed err=%d\n", ret
);
1061 mutex_unlock(&wcn
->hal_mutex
);
1065 static int wcn36xx_smd_process_ptt_msg_rsp(void *buf
, size_t len
,
1066 void **p_ptt_rsp_msg
)
1068 struct wcn36xx_hal_process_ptt_msg_rsp_msg
*rsp
;
1071 ret
= wcn36xx_smd_rsp_status_check(buf
, len
);
1077 wcn36xx_dbg(WCN36XX_DBG_HAL
, "process ptt msg responded with length %d\n",
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
));
1082 if (rsp
->header
.len
> 0) {
1083 *p_ptt_rsp_msg
= kmemdup(rsp
->ptt_msg
, rsp
->header
.len
,
1085 if (!*p_ptt_rsp_msg
)
1091 int wcn36xx_smd_process_ptt_msg(struct wcn36xx
*wcn
,
1092 struct ieee80211_vif
*vif
, void *ptt_msg
, size_t len
,
1095 struct wcn36xx_hal_process_ptt_msg_req_msg
*p_msg_body
;
1098 mutex_lock(&wcn
->hal_mutex
);
1099 p_msg_body
= kmalloc(
1100 sizeof(struct wcn36xx_hal_process_ptt_msg_req_msg
) + len
,
1106 INIT_HAL_PTT_MSG(p_msg_body
, len
);
1108 memcpy(&p_msg_body
->ptt_msg
, ptt_msg
, len
);
1110 PREPARE_HAL_PTT_MSG_BUF(wcn
->hal_buf
, p_msg_body
);
1112 ret
= wcn36xx_smd_send_and_wait(wcn
, p_msg_body
->header
.len
);
1114 wcn36xx_err("Sending hal_process_ptt_msg failed\n");
1117 ret
= wcn36xx_smd_process_ptt_msg_rsp(wcn
->hal_buf
, wcn
->hal_rsp_len
,
1120 wcn36xx_err("process_ptt_msg response failed err=%d\n", ret
);
1126 mutex_unlock(&wcn
->hal_mutex
);
1130 static int wcn36xx_smd_update_scan_params_rsp(void *buf
, size_t len
)
1132 struct wcn36xx_hal_update_scan_params_resp
*rsp
;
1136 /* Remove the PNO version bit */
1137 rsp
->status
&= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK
));
1139 if (WCN36XX_FW_MSG_RESULT_SUCCESS
!= rsp
->status
) {
1140 wcn36xx_warn("error response from update scan\n");
1147 int wcn36xx_smd_update_scan_params(struct wcn36xx
*wcn
,
1148 u8
*channels
, size_t channel_count
)
1150 struct wcn36xx_hal_update_scan_params_req_ex msg_body
;
1153 mutex_lock(&wcn
->hal_mutex
);
1154 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ
);
1156 msg_body
.dot11d_enabled
= false;
1157 msg_body
.dot11d_resolved
= true;
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
;
1167 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
1169 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1170 "hal update scan params channel_count %d\n",
1171 msg_body
.channel_count
);
1173 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1175 wcn36xx_err("Sending hal_update_scan_params failed\n");
1178 ret
= wcn36xx_smd_update_scan_params_rsp(wcn
->hal_buf
,
1181 wcn36xx_err("hal_update_scan_params response failed err=%d\n",
1186 mutex_unlock(&wcn
->hal_mutex
);
1190 static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx
*wcn
,
1191 struct ieee80211_vif
*vif
,
1195 struct wcn36xx_hal_add_sta_self_rsp_msg
*rsp
;
1196 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
1198 if (len
< sizeof(*rsp
))
1203 if (rsp
->status
!= WCN36XX_FW_MSG_RESULT_SUCCESS
) {
1204 wcn36xx_warn("hal add sta self failure: %d\n",
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
);
1213 vif_priv
->self_sta_index
= rsp
->self_sta_index
;
1214 vif_priv
->self_dpu_desc_index
= rsp
->dpu_index
;
1219 int wcn36xx_smd_add_sta_self(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
)
1221 struct wcn36xx_hal_add_sta_self_req msg_body
;
1224 mutex_lock(&wcn
->hal_mutex
);
1225 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_ADD_STA_SELF_REQ
);
1227 memcpy(&msg_body
.self_addr
, vif
->addr
, ETH_ALEN
);
1229 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
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
);
1235 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1237 wcn36xx_err("Sending hal_add_sta_self failed\n");
1240 ret
= wcn36xx_smd_add_sta_self_rsp(wcn
,
1245 wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret
);
1249 mutex_unlock(&wcn
->hal_mutex
);
1253 int wcn36xx_smd_delete_sta_self(struct wcn36xx
*wcn
, u8
*addr
)
1255 struct wcn36xx_hal_del_sta_self_req_msg msg_body
;
1258 mutex_lock(&wcn
->hal_mutex
);
1259 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_DEL_STA_SELF_REQ
);
1261 memcpy(&msg_body
.self_addr
, addr
, ETH_ALEN
);
1263 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
1265 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1267 wcn36xx_err("Sending hal_delete_sta_self failed\n");
1270 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
1272 wcn36xx_err("hal_delete_sta_self response failed err=%d\n",
1277 mutex_unlock(&wcn
->hal_mutex
);
1281 int wcn36xx_smd_delete_sta(struct wcn36xx
*wcn
, u8 sta_index
)
1283 struct wcn36xx_hal_delete_sta_req_msg msg_body
;
1286 mutex_lock(&wcn
->hal_mutex
);
1287 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_DELETE_STA_REQ
);
1289 msg_body
.sta_index
= sta_index
;
1291 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
1293 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1294 "hal delete sta sta_index %d\n",
1295 msg_body
.sta_index
);
1297 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1299 wcn36xx_err("Sending hal_delete_sta failed\n");
1302 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
1304 wcn36xx_err("hal_delete_sta response failed err=%d\n", ret
);
1308 mutex_unlock(&wcn
->hal_mutex
);
1312 static int wcn36xx_smd_join_rsp(void *buf
, size_t len
)
1314 struct wcn36xx_hal_join_rsp_msg
*rsp
;
1316 if (wcn36xx_smd_rsp_status_check(buf
, len
))
1321 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1322 "hal rsp join status %d tx_mgmt_power %d\n",
1323 rsp
->status
, rsp
->tx_mgmt_power
);
1328 int wcn36xx_smd_join(struct wcn36xx
*wcn
, const u8
*bssid
, u8
*vif
, u8 ch
)
1330 struct wcn36xx_hal_join_req_msg msg_body
;
1333 mutex_lock(&wcn
->hal_mutex
);
1334 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_JOIN_REQ
);
1336 memcpy(&msg_body
.bssid
, bssid
, ETH_ALEN
);
1337 memcpy(&msg_body
.self_sta_mac_addr
, vif
, ETH_ALEN
);
1338 msg_body
.channel
= ch
;
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
;
1347 msg_body
.secondary_channel_offset
=
1348 PHY_SINGLE_CHANNEL_CENTERED
;
1350 msg_body
.link_state
= WCN36XX_HAL_LINK_PREASSOC_STATE
;
1352 msg_body
.max_tx_power
= 0xbf;
1353 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
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
);
1360 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1362 wcn36xx_err("Sending hal_join failed\n");
1365 ret
= wcn36xx_smd_join_rsp(wcn
->hal_buf
, wcn
->hal_rsp_len
);
1367 wcn36xx_err("hal_join response failed err=%d\n", ret
);
1371 mutex_unlock(&wcn
->hal_mutex
);
1375 int wcn36xx_smd_set_link_st(struct wcn36xx
*wcn
, const u8
*bssid
,
1377 enum wcn36xx_hal_link_state state
)
1379 struct wcn36xx_hal_set_link_state_req_msg msg_body
;
1382 mutex_lock(&wcn
->hal_mutex
);
1383 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_SET_LINK_ST_REQ
);
1385 memcpy(&msg_body
.bssid
, bssid
, ETH_ALEN
);
1386 memcpy(&msg_body
.self_mac_addr
, sta_mac
, ETH_ALEN
);
1387 msg_body
.state
= state
;
1389 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
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
);
1395 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1397 wcn36xx_err("Sending hal_set_link_st failed\n");
1400 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
1402 wcn36xx_err("hal_set_link_st response failed err=%d\n", ret
);
1406 mutex_unlock(&wcn
->hal_mutex
);
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
)
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
;
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
)
1453 struct wcn36xx_sta
*sta_priv
= NULL
;
1454 struct wcn36xx_hal_config_sta_params sta_par_v0
;
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
);
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
));
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
);
1472 static int wcn36xx_smd_config_sta_rsp(struct wcn36xx
*wcn
,
1473 struct ieee80211_sta
*sta
,
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
);
1481 if (len
< sizeof(*rsp
))
1485 params
= &rsp
->params
;
1487 if (params
->status
!= WCN36XX_FW_MSG_RESULT_SUCCESS
) {
1488 wcn36xx_warn("hal config sta response failure: %d\n",
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
;
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
);
1505 static int wcn36xx_smd_config_sta_v1(struct wcn36xx
*wcn
,
1506 struct ieee80211_vif
*vif
,
1507 struct ieee80211_sta
*sta
)
1509 struct wcn36xx_hal_config_sta_req_msg_v1 msg_body
;
1510 struct wcn36xx_hal_config_sta_params_v1
*sta_params
;
1512 if (wcn
->rf_id
== RF_IRIS_WCN3680
) {
1513 INIT_HAL_MSG_V1(msg_body
, WCN36XX_HAL_CONFIG_STA_REQ
);
1515 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_CONFIG_STA_REQ
);
1516 msg_body
.header
.len
-= WCN36XX_DIFF_STA_PARAMS_V1_NOVHT
;
1519 sta_params
= &msg_body
.sta_params
;
1521 wcn36xx_smd_set_sta_params_v1(wcn
, vif
, sta
, sta_params
);
1523 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
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
);
1530 return wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1533 static int wcn36xx_smd_config_sta_v0(struct wcn36xx
*wcn
,
1534 struct ieee80211_vif
*vif
,
1535 struct ieee80211_sta
*sta
)
1537 struct wcn36xx_hal_config_sta_req_msg msg
;
1538 struct wcn36xx_hal_config_sta_params
*sta_params
;
1540 INIT_HAL_MSG(msg
, WCN36XX_HAL_CONFIG_STA_REQ
);
1542 sta_params
= &msg
.sta_params
;
1544 wcn36xx_smd_set_sta_params(wcn
, vif
, sta
, sta_params
);
1546 PREPARE_HAL_BUF(wcn
->hal_buf
, msg
);
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
);
1554 return wcn36xx_smd_send_and_wait(wcn
, msg
.header
.len
);
1557 int wcn36xx_smd_config_sta(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
,
1558 struct ieee80211_sta
*sta
)
1562 mutex_lock(&wcn
->hal_mutex
);
1564 if (!wcn36xx_is_fw_version(wcn
, 1, 2, 2, 24))
1565 ret
= wcn36xx_smd_config_sta_v1(wcn
, vif
, sta
);
1567 ret
= wcn36xx_smd_config_sta_v0(wcn
, vif
, sta
);
1570 wcn36xx_err("Sending hal_config_sta failed\n");
1573 ret
= wcn36xx_smd_config_sta_rsp(wcn
,
1578 wcn36xx_err("hal_config_sta response failed err=%d\n", ret
);
1582 mutex_unlock(&wcn
->hal_mutex
);
1586 static void wcn36xx_smd_set_bss_params(struct wcn36xx
*wcn
,
1587 struct ieee80211_vif
*vif
,
1588 struct ieee80211_sta
*sta
,
1591 struct wcn36xx_hal_config_bss_params
*bss
)
1593 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
1595 WARN_ON(is_zero_ether_addr(bssid
));
1597 memcpy(&bss
->bssid
, bssid
, ETH_ALEN
);
1599 memcpy(bss
->self_mac_addr
, vif
->addr
, ETH_ALEN
);
1601 if (vif
->type
== NL80211_IFTYPE_STATION
) {
1602 bss
->bss_type
= WCN36XX_HAL_INFRASTRUCTURE_MODE
;
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
;
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
;
1620 wcn36xx_warn("Unknown type for bss config: %d\n", vif
->type
);
1623 if (vif
->type
== NL80211_IFTYPE_STATION
)
1624 wcn36xx_smd_set_bss_nw_type(wcn
, sta
, bss
);
1626 bss
->nw_type
= WCN36XX_HAL_11N_NW_TYPE
;
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;
1633 bss
->beacon_interval
= vif
->bss_conf
.beacon_int
;
1634 bss
->dtim_period
= vif_priv
->dtim_period
;
1636 wcn36xx_smd_set_bss_ht_params(vif
, sta
, bss
);
1638 bss
->oper_channel
= WCN36XX_HW_CHANNEL(wcn
);
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
;
1645 bss
->ext_channel
= IEEE80211_HT_PARAM_CHA_SEC_NONE
;
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
);
1653 bss
->obss_prot_enabled
= 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;
1660 /* FIXME: set acbe, acbk, acvi and acvo */
1662 bss
->ext_set_sta_key_param_valid
= 0;
1664 /* FIXME: set ext_set_sta_key_param */
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
;
1671 vif_priv
->bss_type
= bss
->bss_type
;
1674 static int wcn36xx_smd_config_bss_v1(struct wcn36xx
*wcn
,
1675 struct ieee80211_vif
*vif
,
1676 struct ieee80211_sta
*sta_80211
,
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
;
1687 msg_body
= kzalloc(sizeof(*msg_body
), GFP_KERNEL
);
1691 if (wcn
->rf_id
== RF_IRIS_WCN3680
) {
1692 INIT_HAL_MSG_V1((*msg_body
), WCN36XX_HAL_CONFIG_BSS_REQ
);
1694 INIT_HAL_MSG((*msg_body
), WCN36XX_HAL_CONFIG_BSS_REQ
);
1695 msg_body
->header
.len
-= WCN36XX_DIFF_BSS_PARAMS_V1_NOVHT
;
1698 bss
= &msg_body
->bss_params
;
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
);
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
);
1709 bss
->bss_type
= bss_v0
.bss_type
;
1710 bss
->oper_mode
= bss_v0
.oper_mode
;
1711 bss
->nw_type
= bss_v0
.nw_type
;
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
;
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
;
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
);
1733 bss
->ext_channel
= bss_v0
.ext_channel
;
1736 bss
->reserved
= bss_v0
.reserved
;
1738 memcpy(&bss
->ssid
, &bss_v0
.ssid
,
1739 sizeof(bss_v0
.ssid
));
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
;
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
;
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
));
1764 bss
->ext_set_sta_key_param_valid
=
1765 bss_v0
.ext_set_sta_key_param_valid
;
1767 memcpy(&bss
->ext_set_sta_key_param
,
1768 &bss_v0
.ext_set_sta_key_param
,
1769 sizeof(bss_v0
.acvo
));
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
;
1776 wcn36xx_smd_set_bss_vht_params(vif
, sta_80211
, bss
);
1778 PREPARE_HAL_BUF(wcn
->hal_buf
, (*msg_body
));
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
);
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
);
1790 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
->header
.len
);
1796 static int wcn36xx_smd_config_bss_v0(struct wcn36xx
*wcn
,
1797 struct ieee80211_vif
*vif
,
1798 struct ieee80211_sta
*sta
,
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
;
1807 msg
= kzalloc(sizeof(*msg
), GFP_KERNEL
);
1811 INIT_HAL_MSG((*msg
), WCN36XX_HAL_CONFIG_BSS_REQ
);
1813 bss
= &msg
->bss_params
;
1814 sta_params
= &bss
->sta
;
1816 wcn36xx_smd_set_bss_params(wcn
, vif
, sta
, bssid
, update
, bss
);
1817 wcn36xx_smd_set_sta_params(wcn
, vif
, sta
, sta_params
);
1819 PREPARE_HAL_BUF(wcn
->hal_buf
, (*msg
));
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
);
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
,
1833 ret
= wcn36xx_smd_send_and_wait(wcn
, msg
->header
.len
);
1839 static int wcn36xx_smd_config_bss_rsp(struct wcn36xx
*wcn
,
1840 struct ieee80211_vif
*vif
,
1841 struct ieee80211_sta
*sta
,
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
);
1849 if (len
< sizeof(*rsp
))
1853 params
= &rsp
->bss_rsp_params
;
1855 if (params
->status
!= WCN36XX_FW_MSG_RESULT_SUCCESS
) {
1856 wcn36xx_warn("hal config bss response failure: %d\n",
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
);
1870 vif_priv
->bss_index
= params
->bss_index
;
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
;
1878 vif_priv
->self_ucast_dpu_sign
= params
->ucast_dpu_signature
;
1883 int wcn36xx_smd_config_bss(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
,
1884 struct ieee80211_sta
*sta
, const u8
*bssid
,
1889 mutex_lock(&wcn
->hal_mutex
);
1891 if (!wcn36xx_is_fw_version(wcn
, 1, 2, 2, 24))
1892 ret
= wcn36xx_smd_config_bss_v1(wcn
, vif
, sta
, bssid
, update
);
1894 ret
= wcn36xx_smd_config_bss_v0(wcn
, vif
, sta
, bssid
, update
);
1897 wcn36xx_err("Sending hal_config_bss failed\n");
1900 ret
= wcn36xx_smd_config_bss_rsp(wcn
,
1906 wcn36xx_err("hal_config_bss response failed err=%d\n", ret
);
1909 mutex_unlock(&wcn
->hal_mutex
);
1913 int wcn36xx_smd_delete_bss(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
)
1915 struct wcn36xx_hal_delete_bss_req_msg msg_body
;
1916 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
1919 mutex_lock(&wcn
->hal_mutex
);
1921 if (vif_priv
->bss_index
== WCN36XX_HAL_BSS_INVALID_IDX
)
1924 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_DELETE_BSS_REQ
);
1926 msg_body
.bss_index
= vif_priv
->bss_index
;
1928 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
1930 wcn36xx_dbg(WCN36XX_DBG_HAL
, "hal delete bss %d\n", msg_body
.bss_index
);
1932 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1934 wcn36xx_err("Sending hal_delete_bss failed\n");
1937 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
1939 wcn36xx_err("hal_delete_bss response failed err=%d\n", ret
);
1943 vif_priv
->bss_index
= WCN36XX_HAL_BSS_INVALID_IDX
;
1945 mutex_unlock(&wcn
->hal_mutex
);
1949 int wcn36xx_smd_send_beacon(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
,
1950 struct sk_buff
*skb_beacon
, u16 tim_off
,
1953 struct wcn36xx_hal_send_beacon_req_msg msg_body
;
1954 int ret
, pad
, pvm_len
;
1956 mutex_lock(&wcn
->hal_mutex
);
1957 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_SEND_BEACON_REQ
);
1959 pvm_len
= skb_beacon
->data
[tim_off
+ 1] - 3;
1960 pad
= TIM_MIN_PVM_SIZE
- pvm_len
;
1962 /* Padding is irrelevant to mesh mode since tim_off is always 0. */
1963 if (vif
->type
== NL80211_IFTYPE_MESH_POINT
)
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;
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
);
1976 memcpy(msg_body
.beacon
, skb_beacon
->data
, skb_beacon
->len
);
1977 memcpy(msg_body
.bssid
, vif
->addr
, ETH_ALEN
);
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
1986 wcn36xx_dbg(WCN36XX_DBG_HAL
, "Pad TIM PVM. %d bytes at %d\n",
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
;
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;
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
);
2004 wcn36xx_dbg(WCN36XX_DBG_HAL
,
2005 "hal send beacon beacon_length %d\n",
2006 msg_body
.beacon_length
);
2008 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2010 wcn36xx_err("Sending hal_send_beacon failed\n");
2013 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2015 wcn36xx_err("hal_send_beacon response failed err=%d\n", ret
);
2019 mutex_unlock(&wcn
->hal_mutex
);
2023 int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx
*wcn
,
2024 struct ieee80211_vif
*vif
,
2025 struct sk_buff
*skb
)
2027 struct wcn36xx_hal_send_probe_resp_req_msg msg
;
2030 mutex_lock(&wcn
->hal_mutex
);
2031 INIT_HAL_MSG(msg
, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ
);
2033 if (skb
->len
> BEACON_TEMPLATE_SIZE
) {
2034 wcn36xx_warn("probe response template is too big: %d\n",
2040 msg
.probe_resp_template_len
= skb
->len
;
2041 memcpy(&msg
.probe_resp_template
, skb
->data
, skb
->len
);
2043 memcpy(msg
.bssid
, vif
->addr
, ETH_ALEN
);
2045 PREPARE_HAL_BUF(wcn
->hal_buf
, msg
);
2047 wcn36xx_dbg(WCN36XX_DBG_HAL
,
2048 "hal update probe rsp len %d bssid %pM\n",
2049 msg
.probe_resp_template_len
, msg
.bssid
);
2051 ret
= wcn36xx_smd_send_and_wait(wcn
, msg
.header
.len
);
2053 wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n");
2056 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2058 wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n",
2063 mutex_unlock(&wcn
->hal_mutex
);
2067 int wcn36xx_smd_set_stakey(struct wcn36xx
*wcn
,
2068 enum ani_ed_type enc_type
,
2074 struct wcn36xx_hal_set_sta_key_req_msg msg_body
;
2077 mutex_lock(&wcn
->hal_mutex
);
2078 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_SET_STAKEY_REQ
);
2080 msg_body
.set_sta_key_params
.sta_index
= sta_index
;
2081 msg_body
.set_sta_key_params
.enc_type
= enc_type
;
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;
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
);
2097 msg_body
.set_sta_key_params
.single_tid_rc
= 1;
2099 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2101 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2103 wcn36xx_err("Sending hal_set_stakey failed\n");
2106 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2108 wcn36xx_err("hal_set_stakey response failed err=%d\n", ret
);
2112 mutex_unlock(&wcn
->hal_mutex
);
2116 int wcn36xx_smd_set_bsskey(struct wcn36xx
*wcn
,
2117 enum ani_ed_type enc_type
,
2123 struct wcn36xx_hal_set_bss_key_req_msg msg_body
;
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
);
2138 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2140 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2142 wcn36xx_err("Sending hal_set_bsskey failed\n");
2145 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2147 wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret
);
2151 mutex_unlock(&wcn
->hal_mutex
);
2155 int wcn36xx_smd_remove_stakey(struct wcn36xx
*wcn
,
2156 enum ani_ed_type enc_type
,
2160 struct wcn36xx_hal_remove_sta_key_req_msg msg_body
;
2163 mutex_lock(&wcn
->hal_mutex
);
2164 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_RMV_STAKEY_REQ
);
2166 msg_body
.sta_idx
= sta_index
;
2167 msg_body
.enc_type
= enc_type
;
2168 msg_body
.key_id
= keyidx
;
2170 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2172 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2174 wcn36xx_err("Sending hal_remove_stakey failed\n");
2177 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2179 wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret
);
2183 mutex_unlock(&wcn
->hal_mutex
);
2187 int wcn36xx_smd_remove_bsskey(struct wcn36xx
*wcn
,
2188 enum ani_ed_type enc_type
,
2192 struct wcn36xx_hal_remove_bss_key_req_msg msg_body
;
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
;
2201 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2203 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2205 wcn36xx_err("Sending hal_remove_bsskey failed\n");
2208 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2210 wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret
);
2214 mutex_unlock(&wcn
->hal_mutex
);
2218 int wcn36xx_smd_enter_bmps(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
)
2220 struct wcn36xx_hal_enter_bmps_req_msg msg_body
;
2221 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
2224 mutex_lock(&wcn
->hal_mutex
);
2225 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_ENTER_BMPS_REQ
);
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
;
2231 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2233 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2235 wcn36xx_err("Sending hal_enter_bmps failed\n");
2238 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2240 wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret
);
2244 mutex_unlock(&wcn
->hal_mutex
);
2248 int wcn36xx_smd_exit_bmps(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
)
2250 struct wcn36xx_hal_exit_bmps_req_msg msg_body
;
2251 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
2254 mutex_lock(&wcn
->hal_mutex
);
2255 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_EXIT_BMPS_REQ
);
2257 msg_body
.bss_index
= vif_priv
->bss_index
;
2258 msg_body
.send_data_null
= 1;
2260 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2262 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2264 wcn36xx_err("Sending hal_exit_bmps failed\n");
2267 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2269 wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret
);
2273 mutex_unlock(&wcn
->hal_mutex
);
2277 int wcn36xx_smd_enter_imps(struct wcn36xx
*wcn
)
2279 struct wcn36xx_hal_enter_imps_req_msg msg_body
;
2282 mutex_lock(&wcn
->hal_mutex
);
2283 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_ENTER_IMPS_REQ
);
2285 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2287 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2289 wcn36xx_err("Sending hal_enter_imps failed\n");
2292 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2294 wcn36xx_err("hal_enter_imps response failed err=%d\n", ret
);
2298 wcn36xx_dbg(WCN36XX_DBG_HAL
, "Entered idle mode\n");
2300 mutex_unlock(&wcn
->hal_mutex
);
2304 int wcn36xx_smd_exit_imps(struct wcn36xx
*wcn
)
2306 struct wcn36xx_hal_exit_imps_req_msg msg_body
;
2309 mutex_lock(&wcn
->hal_mutex
);
2310 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_EXIT_IMPS_REQ
);
2312 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2314 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2316 wcn36xx_err("Sending hal_exit_imps failed\n");
2319 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2321 wcn36xx_err("hal_exit_imps response failed err=%d\n", ret
);
2324 wcn36xx_dbg(WCN36XX_DBG_HAL
, "Exited idle mode\n");
2326 mutex_unlock(&wcn
->hal_mutex
);
2330 int wcn36xx_smd_set_power_params(struct wcn36xx
*wcn
, bool ignore_dtim
)
2332 struct wcn36xx_hal_set_power_params_req_msg msg_body
;
2335 mutex_lock(&wcn
->hal_mutex
);
2336 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_SET_POWER_PARAMS_REQ
);
2339 * When host is down ignore every second dtim
2342 msg_body
.ignore_dtim
= 1;
2343 msg_body
.dtim_period
= 2;
2345 msg_body
.listen_interval
= WCN36XX_LISTEN_INTERVAL(wcn
);
2347 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2349 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2351 wcn36xx_err("Sending hal_set_power_params failed\n");
2356 mutex_unlock(&wcn
->hal_mutex
);
2360 /* Notice: This function should be called after associated, or else it
2363 int wcn36xx_smd_keep_alive_req(struct wcn36xx
*wcn
,
2364 struct ieee80211_vif
*vif
,
2367 struct wcn36xx_hal_keep_alive_req_msg msg_body
;
2368 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
2371 mutex_lock(&wcn
->hal_mutex
);
2372 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_KEEP_ALIVE_REQ
);
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 */
2381 wcn36xx_warn("unknown keep alive packet type %d\n", packet_type
);
2386 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2388 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2390 wcn36xx_err("Sending hal_keep_alive failed\n");
2393 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2395 wcn36xx_err("hal_keep_alive response failed err=%d\n", ret
);
2399 mutex_unlock(&wcn
->hal_mutex
);
2403 int wcn36xx_smd_dump_cmd_req(struct wcn36xx
*wcn
, u32 arg1
, u32 arg2
,
2404 u32 arg3
, u32 arg4
, u32 arg5
)
2406 struct wcn36xx_hal_dump_cmd_req_msg msg_body
;
2409 mutex_lock(&wcn
->hal_mutex
);
2410 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_DUMP_COMMAND_REQ
);
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
;
2418 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2420 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2422 wcn36xx_err("Sending hal_dump_cmd failed\n");
2425 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2427 wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret
);
2431 mutex_unlock(&wcn
->hal_mutex
);
2435 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx
*wcn
)
2437 struct wcn36xx_hal_feat_caps_msg msg_body
, *rsp
;
2440 mutex_lock(&wcn
->hal_mutex
);
2441 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ
);
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
);
2451 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2453 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2455 wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
2458 if (wcn
->hal_rsp_len
!= sizeof(*rsp
)) {
2459 wcn36xx_err("Invalid hal_feature_caps_exchange response");
2463 rsp
= (struct wcn36xx_hal_feat_caps_msg
*) wcn
->hal_buf
;
2465 for (i
= 0; i
< WCN36XX_HAL_CAPS_SIZE
; i
++)
2466 wcn
->fw_feat_caps
[i
] = rsp
->feat_caps
[i
];
2468 mutex_unlock(&wcn
->hal_mutex
);
2472 static int wcn36xx_smd_add_ba_session_rsp(void *buf
, int len
, u8
*session
)
2474 struct wcn36xx_hal_add_ba_session_rsp_msg
*rsp
;
2476 if (len
< sizeof(*rsp
))
2480 if (rsp
->status
!= WCN36XX_FW_MSG_RESULT_SUCCESS
)
2483 *session
= rsp
->ba_session_id
;
2488 int wcn36xx_smd_add_ba_session(struct wcn36xx
*wcn
,
2489 struct ieee80211_sta
*sta
,
2495 struct wcn36xx_hal_add_ba_session_req_msg msg_body
;
2499 mutex_lock(&wcn
->hal_mutex
);
2500 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_ADD_BA_SESSION_REQ
);
2502 msg_body
.sta_index
= sta_index
;
2503 memcpy(&msg_body
.mac_addr
, sta
->addr
, ETH_ALEN
);
2504 msg_body
.dialog_token
= 0x10;
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;
2512 msg_body
.ssn
= *ssn
;
2513 msg_body
.direction
= direction
;
2515 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2517 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2519 wcn36xx_err("Sending hal_add_ba_session failed\n");
2522 ret
= wcn36xx_smd_add_ba_session_rsp(wcn
->hal_buf
, wcn
->hal_rsp_len
,
2525 wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret
);
2532 mutex_unlock(&wcn
->hal_mutex
);
2536 int wcn36xx_smd_add_ba(struct wcn36xx
*wcn
, u8 session_id
)
2538 struct wcn36xx_hal_add_ba_req_msg msg_body
;
2541 mutex_lock(&wcn
->hal_mutex
);
2542 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_ADD_BA_REQ
);
2544 msg_body
.session_id
= session_id
;
2545 msg_body
.win_size
= WCN36XX_AGGR_BUFFER_SIZE
;
2547 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2549 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2551 wcn36xx_err("Sending hal_add_ba failed\n");
2554 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2556 wcn36xx_err("hal_add_ba response failed err=%d\n", ret
);
2560 mutex_unlock(&wcn
->hal_mutex
);
2564 int wcn36xx_smd_del_ba(struct wcn36xx
*wcn
, u16 tid
, u8 direction
, u8 sta_index
)
2566 struct wcn36xx_hal_del_ba_req_msg msg_body
;
2569 mutex_lock(&wcn
->hal_mutex
);
2570 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_DEL_BA_REQ
);
2572 msg_body
.sta_index
= sta_index
;
2574 msg_body
.direction
= direction
;
2575 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2577 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2579 wcn36xx_err("Sending hal_del_ba failed\n");
2582 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2584 wcn36xx_err("hal_del_ba response failed err=%d\n", ret
);
2588 mutex_unlock(&wcn
->hal_mutex
);
2592 int wcn36xx_smd_get_stats(struct wcn36xx
*wcn
, u8 sta_index
, u32 stats_mask
,
2593 struct station_info
*sinfo
)
2595 struct wcn36xx_hal_stats_req_msg msg_body
;
2596 struct wcn36xx_hal_stats_rsp_msg
*rsp
;
2600 if (stats_mask
& ~HAL_GLOBAL_CLASS_A_STATS_INFO
) {
2601 wcn36xx_err("stats_mask 0x%x contains unimplemented types\n",
2606 mutex_lock(&wcn
->hal_mutex
);
2607 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_GET_STATS_REQ
);
2609 msg_body
.sta_id
= sta_index
;
2610 msg_body
.stats_mask
= stats_mask
;
2612 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2614 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2616 wcn36xx_err("sending hal_get_stats failed\n");
2620 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2622 wcn36xx_err("hal_get_stats response failed err=%d\n", ret
);
2626 rsp
= (struct wcn36xx_hal_stats_rsp_msg
*)wcn
->hal_buf
;
2627 rsp_body
= (wcn
->hal_buf
+ sizeof(struct wcn36xx_hal_stats_rsp_msg
));
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
);
2635 if (rsp
->stats_mask
& HAL_GLOBAL_CLASS_A_STATS_INFO
) {
2636 struct ani_global_class_a_stats_info
*stats_info
= rsp_body
;
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
);
2643 mutex_unlock(&wcn
->hal_mutex
);
2648 static int wcn36xx_smd_trigger_ba_rsp(void *buf
, int len
, struct add_ba_info
*ba_info
)
2650 struct wcn36xx_hal_trigger_ba_rsp_candidate
*candidate
;
2651 struct wcn36xx_hal_trigger_ba_rsp_msg
*rsp
;
2654 if (len
< sizeof(*rsp
))
2659 if (rsp
->candidate_cnt
< 1)
2660 return rsp
->status
? rsp
->status
: -EINVAL
;
2662 candidate
= (struct wcn36xx_hal_trigger_ba_rsp_candidate
*)(buf
+ sizeof(*rsp
));
2664 for (i
= 0; i
< STACFG_MAX_TC
; i
++) {
2665 ba_info
[i
] = candidate
->ba_info
[i
];
2671 int wcn36xx_smd_trigger_ba(struct wcn36xx
*wcn
, u8 sta_index
, u16 tid
, u16
*ssn
)
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
];
2678 if (tid
>= STACFG_MAX_TC
)
2681 mutex_lock(&wcn
->hal_mutex
);
2682 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_TRIGGER_BA_REQ
);
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
);
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
;
2694 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2696 wcn36xx_err("Sending hal_trigger_ba failed\n");
2699 ret
= wcn36xx_smd_trigger_ba_rsp(wcn
->hal_buf
, wcn
->hal_rsp_len
, ba_info
);
2701 wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret
);
2705 mutex_unlock(&wcn
->hal_mutex
);
2708 *ssn
= ba_info
[tid
].starting_seq_num
;
2713 static int wcn36xx_smd_tx_compl_ind(struct wcn36xx
*wcn
, void *buf
, size_t len
)
2715 struct wcn36xx_hal_tx_compl_ind_msg
*rsp
= buf
;
2717 if (len
!= sizeof(*rsp
)) {
2718 wcn36xx_warn("Bad TX complete indication\n");
2722 wcn36xx_dxe_tx_ack_ind(wcn
, rsp
->status
);
2727 static int wcn36xx_smd_hw_scan_ind(struct wcn36xx
*wcn
, void *buf
, size_t len
)
2729 struct wcn36xx_hal_scan_offload_ind
*rsp
= buf
;
2730 struct cfg80211_scan_info scan_info
= {};
2732 if (len
!= sizeof(*rsp
)) {
2733 wcn36xx_warn("Corrupted delete scan indication\n");
2737 wcn36xx_dbg(WCN36XX_DBG_HAL
, "scan indication (type %x)\n", rsp
->type
);
2739 switch (rsp
->type
) {
2740 case WCN36XX_HAL_SCAN_IND_FAILED
:
2741 case WCN36XX_HAL_SCAN_IND_DEQUEUED
:
2742 scan_info
.aborted
= true;
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
);
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
:
2758 wcn36xx_warn("Unknown scan indication type %x\n", rsp
->type
);
2764 static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx
*wcn
,
2768 struct wcn36xx_hal_missed_beacon_ind_msg
*rsp
= buf
;
2769 struct ieee80211_vif
*vif
= NULL
;
2770 struct wcn36xx_vif
*tmp
;
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",
2777 vif
= wcn36xx_priv_to_vif(tmp
);
2778 ieee80211_beacon_loss(vif
);
2783 if (len
!= sizeof(*rsp
)) {
2784 wcn36xx_warn("Corrupted missed beacon indication\n");
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",
2792 vif
= wcn36xx_priv_to_vif(tmp
);
2793 ieee80211_beacon_loss(vif
);
2798 wcn36xx_warn("BSS index %d not found\n", rsp
->bss_index
);
2802 static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx
*wcn
,
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
;
2813 if (len
!= sizeof(*rsp
)) {
2814 wcn36xx_warn("Corrupted delete sta indication\n");
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
);
2822 list_for_each_entry(vif_priv
, &wcn
->vif_list
, list
) {
2824 vif
= wcn36xx_priv_to_vif(vif_priv
);
2826 if (vif
->type
== NL80211_IFTYPE_STATION
) {
2827 /* We could call ieee80211_find_sta too, but checking
2828 * bss_conf is clearer.
2830 bss_conf
= &vif
->bss_conf
;
2831 if (vif_priv
->sta_assoc
&&
2832 !memcmp(bss_conf
->bssid
, rsp
->addr2
, ETH_ALEN
)) {
2834 wcn36xx_dbg(WCN36XX_DBG_HAL
,
2835 "connection loss bss_index %d\n",
2836 vif_priv
->bss_index
);
2837 ieee80211_connection_loss(vif
);
2840 sta
= ieee80211_find_sta(vif
, rsp
->addr2
);
2843 ieee80211_report_low_ack(sta
, 0);
2852 wcn36xx_warn("BSS or STA with addr %pM not found\n", rsp
->addr2
);
2856 static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx
*wcn
,
2860 struct wcn36xx_hal_print_reg_info_ind
*rsp
= buf
;
2863 if (len
< sizeof(*rsp
)) {
2864 wcn36xx_warn("Corrupted print reg info indication\n");
2868 wcn36xx_dbg(WCN36XX_DBG_HAL
,
2869 "reginfo indication, scenario: 0x%x reason: 0x%x\n",
2870 rsp
->scenario
, rsp
->reason
);
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
);
2880 int wcn36xx_smd_update_cfg(struct wcn36xx
*wcn
, u32 cfg_id
, u32 value
)
2882 struct wcn36xx_hal_update_cfg_req_msg msg_body
, *body
;
2886 mutex_lock(&wcn
->hal_mutex
);
2887 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_UPDATE_CFG_REQ
);
2889 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2891 body
= (struct wcn36xx_hal_update_cfg_req_msg
*) wcn
->hal_buf
;
2892 len
= msg_body
.header
.len
;
2894 put_cfg_tlv_u32(wcn
, &len
, cfg_id
, value
);
2895 body
->header
.len
= len
;
2896 body
->len
= len
- sizeof(*body
);
2898 ret
= wcn36xx_smd_send_and_wait(wcn
, body
->header
.len
);
2900 wcn36xx_err("Sending hal_update_cfg failed\n");
2903 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2905 wcn36xx_err("hal_update_cfg response failed err=%d\n", ret
);
2909 mutex_unlock(&wcn
->hal_mutex
);
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
)
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
;
2921 mutex_lock(&wcn
->hal_mutex
);
2923 msg_body
= (struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg
*)
2925 INIT_HAL_MSG(*msg_body
, WCN36XX_HAL_8023_MULTICAST_LIST_REQ
);
2927 /* An empty list means all mc traffic will be received */
2929 memcpy(&msg_body
->mc_addr_list
, fp
,
2930 sizeof(msg_body
->mc_addr_list
));
2932 msg_body
->mc_addr_list
.mc_addr_count
= 0;
2934 msg_body
->mc_addr_list
.bss_index
= vif_priv
->bss_index
;
2936 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
->header
.len
);
2938 wcn36xx_err("Sending HAL_8023_MULTICAST_LIST failed\n");
2941 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2943 wcn36xx_err("HAL_8023_MULTICAST_LIST rsp failed err=%d\n", ret
);
2947 mutex_unlock(&wcn
->hal_mutex
);
2951 int wcn36xx_smd_arp_offload(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
,
2954 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
2955 struct wcn36xx_hal_host_offload_req_msg msg_body
;
2958 mutex_lock(&wcn
->hal_mutex
);
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
;
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
));
2969 msg_body
.ns_offload_params
.bss_index
= vif_priv
->bss_index
;
2971 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2973 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2975 wcn36xx_err("Sending host_offload_arp failed\n");
2978 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2980 wcn36xx_err("host_offload_arp failed err=%d\n", ret
);
2984 mutex_unlock(&wcn
->hal_mutex
);
2988 #if IS_ENABLED(CONFIG_IPV6)
2989 int wcn36xx_smd_ipv6_ns_offload(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
,
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
;
2998 mutex_lock(&wcn
->hal_mutex
);
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
;
3004 ho_params
->offload_type
= WCN36XX_HAL_IPV6_NS_OFFLOAD
;
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;
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;
3024 memcpy(&ns_params
->self_addr
, vif
->addr
, ETH_ALEN
);
3025 ns_params
->bss_index
= vif_priv
->bss_index
;
3027 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
3029 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
3031 wcn36xx_err("Sending host_offload_arp failed\n");
3034 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
3036 wcn36xx_err("host_offload_arp failed err=%d\n", ret
);
3040 mutex_unlock(&wcn
->hal_mutex
);
3044 int wcn36xx_smd_ipv6_ns_offload(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
,
3051 int wcn36xx_smd_gtk_offload(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
,
3054 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
3055 struct wcn36xx_hal_gtk_offload_req_msg msg_body
;
3058 mutex_lock(&wcn
->hal_mutex
);
3060 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_GTK_OFFLOAD_REQ
);
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
;
3069 msg_body
.flags
= WCN36XX_HAL_GTK_OFFLOAD_FLAGS_DISABLE
;
3072 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
3074 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
3076 wcn36xx_err("Sending host_offload_arp failed\n");
3079 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
3081 wcn36xx_err("host_offload_arp failed err=%d\n", ret
);
3085 mutex_unlock(&wcn
->hal_mutex
);
3089 static int wcn36xx_smd_gtk_offload_get_info_rsp(struct wcn36xx
*wcn
,
3090 struct ieee80211_vif
*vif
)
3092 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
3093 struct wcn36xx_hal_gtk_offload_get_info_rsp_msg
*rsp
;
3096 if (wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
))
3099 rsp
= (struct wcn36xx_hal_gtk_offload_get_info_rsp_msg
*)wcn
->hal_buf
;
3101 if (rsp
->bss_index
!= vif_priv
->bss_index
) {
3102 wcn36xx_err("gtk_offload_info invalid response bss index %d\n",
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
);
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
,
3130 int wcn36xx_smd_gtk_offload_get_info(struct wcn36xx
*wcn
,
3131 struct ieee80211_vif
*vif
)
3133 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
3134 struct wcn36xx_hal_gtk_offload_get_info_req_msg msg_body
;
3137 mutex_lock(&wcn
->hal_mutex
);
3139 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_GTK_OFFLOAD_GETINFO_REQ
);
3141 msg_body
.bss_index
= vif_priv
->bss_index
;
3143 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
3145 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
3147 wcn36xx_err("Sending gtk_offload_get_info failed\n");
3150 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
3152 wcn36xx_err("gtk_offload_get_info failed err=%d\n", ret
);
3155 ret
= wcn36xx_smd_gtk_offload_get_info_rsp(wcn
, vif
);
3157 mutex_unlock(&wcn
->hal_mutex
);
3161 int wcn36xx_smd_wlan_host_suspend_ind(struct wcn36xx
*wcn
)
3163 struct wcn36xx_hal_wlan_host_suspend_ind_msg msg_body
;
3166 mutex_lock(&wcn
->hal_mutex
);
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
);
3173 ret
= rpmsg_send(wcn
->smd_channel
, wcn
->hal_buf
, msg_body
.header
.len
);
3175 mutex_unlock(&wcn
->hal_mutex
);
3180 int wcn36xx_smd_host_resume(struct wcn36xx
*wcn
)
3182 struct wcn36xx_hal_wlan_host_resume_req_msg msg_body
;
3183 struct wcn36xx_hal_host_resume_rsp_msg
*rsp
;
3186 mutex_lock(&wcn
->hal_mutex
);
3188 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_HOST_RESUME_REQ
);
3189 msg_body
.configured_mcst_bcst_filter_setting
= 0;
3191 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
3193 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
3195 wcn36xx_err("Sending wlan_host_resume failed\n");
3198 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
3200 wcn36xx_err("wlan_host_resume err=%d\n", ret
);
3204 rsp
= (struct wcn36xx_hal_host_resume_rsp_msg
*)wcn
->hal_buf
;
3206 wcn36xx_warn("wlan_host_resume status=%d\n", rsp
->status
);
3209 mutex_unlock(&wcn
->hal_mutex
);
3214 #define BEACON_FILTER(eid, presence, offs, val, mask, ref_val) \
3216 .element_id = eid, \
3217 .check_ie_presence = presence, \
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),
3253 int wcn36xx_smd_add_beacon_filter(struct wcn36xx
*wcn
,
3254 struct ieee80211_vif
*vif
)
3256 struct wcn36xx_hal_add_bcn_filter_req_msg msg_body
, *body
;
3257 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
3259 size_t payload_size
;
3262 if (!wcn36xx_firmware_get_feat_caps(wcn
->fw_feat_caps
, BCN_FILTER
))
3265 mutex_lock(&wcn
->hal_mutex
);
3266 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_ADD_BCN_FILTER_REQ
);
3268 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
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
;
3277 payload
= ((u8
*)body
) + body
->header
.len
;
3278 payload_size
= sizeof(bcn_filter_ies
);
3279 memcpy(payload
, &bcn_filter_ies
, payload_size
);
3281 body
->header
.len
+= payload_size
;
3283 ret
= wcn36xx_smd_send_and_wait(wcn
, body
->header
.len
);
3285 wcn36xx_err("Sending add bcn_filter failed\n");
3289 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
3291 wcn36xx_err("add bcn filter response failed err=%d\n", ret
);
3295 mutex_unlock(&wcn
->hal_mutex
);
3299 int wcn36xx_smd_rsp_process(struct rpmsg_device
*rpdev
,
3300 void *buf
, int len
, void *priv
, u32 addr
)
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
);
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
);
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
);
3371 wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
3372 msg_header
->msg_type
);
3376 msg_ind
->msg_len
= len
;
3377 memcpy(msg_ind
->msg
, buf
, len
);
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");
3386 wcn36xx_err("SMD_EVENT (%d) not supported\n",
3387 msg_header
->msg_type
);
3393 static void wcn36xx_ind_smd_work(struct work_struct
*work
)
3395 struct wcn36xx
*wcn
=
3396 container_of(work
, struct wcn36xx
, hal_ind_work
);
3399 struct wcn36xx_hal_msg_header
*msg_header
;
3400 struct wcn36xx_hal_ind_msg
*hal_ind_msg
;
3401 unsigned long flags
;
3403 spin_lock_irqsave(&wcn
->hal_ind_lock
, flags
);
3405 if (list_empty(&wcn
->hal_ind_queue
)) {
3406 spin_unlock_irqrestore(&wcn
->hal_ind_lock
, flags
);
3410 hal_ind_msg
= list_first_entry(&wcn
->hal_ind_queue
,
3411 struct wcn36xx_hal_ind_msg
,
3413 list_del(&hal_ind_msg
->list
);
3414 spin_unlock_irqrestore(&wcn
->hal_ind_lock
, flags
);
3416 msg_header
= (struct wcn36xx_hal_msg_header
*)hal_ind_msg
->msg
;
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
:
3423 case WCN36XX_HAL_OTA_TX_COMPL_IND
:
3424 wcn36xx_smd_tx_compl_ind(wcn
,
3426 hal_ind_msg
->msg_len
);
3428 case WCN36XX_HAL_MISSED_BEACON_IND
:
3429 wcn36xx_smd_missed_beacon_ind(wcn
,
3431 hal_ind_msg
->msg_len
);
3433 case WCN36XX_HAL_DELETE_STA_CONTEXT_IND
:
3434 wcn36xx_smd_delete_sta_context_ind(wcn
,
3436 hal_ind_msg
->msg_len
);
3438 case WCN36XX_HAL_PRINT_REG_INFO_IND
:
3439 wcn36xx_smd_print_reg_info_ind(wcn
,
3441 hal_ind_msg
->msg_len
);
3443 case WCN36XX_HAL_SCAN_OFFLOAD_IND
:
3444 wcn36xx_smd_hw_scan_ind(wcn
, hal_ind_msg
->msg
,
3445 hal_ind_msg
->msg_len
);
3448 wcn36xx_err("SMD_EVENT (%d) not supported\n",
3449 msg_header
->msg_type
);
3456 int wcn36xx_smd_open(struct wcn36xx
*wcn
)
3458 wcn
->hal_ind_wq
= create_freezable_workqueue("wcn36xx_smd_ind");
3459 if (!wcn
->hal_ind_wq
)
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
);
3469 void wcn36xx_smd_close(struct wcn36xx
*wcn
)
3471 struct wcn36xx_hal_ind_msg
*msg
, *tmp
;
3473 cancel_work_sync(&wcn
->hal_ind_work
);
3474 destroy_workqueue(wcn
->hal_ind_wq
);
3476 list_for_each_entry_safe(msg
, tmp
, &wcn
->hal_ind_queue
, list
)