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/etherdevice.h>
20 #include <linux/firmware.h>
21 #include <linux/bitops.h>
22 #include <linux/rpmsg.h>
25 struct wcn36xx_cfg_val
{
30 #define WCN36XX_CFG_VAL(id, val) \
32 .cfg_id = WCN36XX_HAL_CFG_ ## id, \
36 static struct wcn36xx_cfg_val wcn36xx_cfg_vals
[] = {
37 WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA
, 1),
38 WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA
, 1),
39 WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE
, 0),
40 WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN
, 785),
41 WCN36XX_CFG_VAL(CAL_PERIOD
, 5),
42 WCN36XX_CFG_VAL(CAL_CONTROL
, 1),
43 WCN36XX_CFG_VAL(PROXIMITY
, 0),
44 WCN36XX_CFG_VAL(NETWORK_DENSITY
, 3),
45 WCN36XX_CFG_VAL(MAX_MEDIUM_TIME
, 6000),
46 WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU
, 64),
47 WCN36XX_CFG_VAL(RTS_THRESHOLD
, 2347),
48 WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT
, 15),
49 WCN36XX_CFG_VAL(LONG_RETRY_LIMIT
, 15),
50 WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD
, 8000),
51 WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO
, 5),
52 WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE
, 10),
53 WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO
, 15),
54 WCN36XX_CFG_VAL(FIXED_RATE
, 0),
55 WCN36XX_CFG_VAL(RETRYRATE_POLICY
, 4),
56 WCN36XX_CFG_VAL(RETRYRATE_SECONDARY
, 0),
57 WCN36XX_CFG_VAL(RETRYRATE_TERTIARY
, 0),
58 WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION
, 5),
59 WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ
, 1),
60 WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ
, 5),
61 WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ
, 5),
62 WCN36XX_CFG_VAL(MAX_BA_SESSIONS
, 40),
63 WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT
, 200),
64 WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER
, 1),
65 WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR
, 1),
66 WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE
, 20),
67 WCN36XX_CFG_VAL(STATS_PERIOD
, 10),
68 WCN36XX_CFG_VAL(CFP_MAX_DURATION
, 30000),
69 WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED
, 0),
70 WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH
, 128),
71 WCN36XX_CFG_VAL(MAX_BA_BUFFERS
, 2560),
72 WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE
, 0),
73 WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE
, 1),
74 WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP
, 1),
75 WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION
, 0),
76 WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT
, 120000),
77 WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN
, 30000),
78 WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT
, 10),
79 WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER
, 0),
80 WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE
, 133), /* MCS 5 */
81 WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT
, 1000),
84 static struct wcn36xx_cfg_val wcn3680_cfg_vals
[] = {
85 WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA
, 1),
86 WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA
, 1),
87 WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE
, 0),
88 WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN
, 785),
89 WCN36XX_CFG_VAL(CAL_PERIOD
, 5),
90 WCN36XX_CFG_VAL(CAL_CONTROL
, 1),
91 WCN36XX_CFG_VAL(PROXIMITY
, 0),
92 WCN36XX_CFG_VAL(NETWORK_DENSITY
, 3),
93 WCN36XX_CFG_VAL(MAX_MEDIUM_TIME
, 4096),
94 WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU
, 64),
95 WCN36XX_CFG_VAL(RTS_THRESHOLD
, 2347),
96 WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT
, 15),
97 WCN36XX_CFG_VAL(LONG_RETRY_LIMIT
, 15),
98 WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD
, 8000),
99 WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO
, 5),
100 WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE
, 10),
101 WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO
, 15),
102 WCN36XX_CFG_VAL(FIXED_RATE
, 0),
103 WCN36XX_CFG_VAL(RETRYRATE_POLICY
, 4),
104 WCN36XX_CFG_VAL(RETRYRATE_SECONDARY
, 0),
105 WCN36XX_CFG_VAL(RETRYRATE_TERTIARY
, 0),
106 WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION
, 5),
107 WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ
, 1),
108 WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ
, 5),
109 WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_24GHZ
, 1),
110 WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ
, 5),
111 WCN36XX_CFG_VAL(MAX_BA_SESSIONS
, 40),
112 WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT
, 200),
113 WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER
, 1),
114 WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR
, 1),
115 WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE
, 20),
116 WCN36XX_CFG_VAL(STATS_PERIOD
, 10),
117 WCN36XX_CFG_VAL(CFP_MAX_DURATION
, 30000),
118 WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED
, 0),
119 WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH
, 128),
120 WCN36XX_CFG_VAL(MAX_BA_BUFFERS
, 2560),
121 WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE
, 0),
122 WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE
, 1),
123 WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP
, 1),
124 WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION
, 0),
125 WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT
, 120000),
126 WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN
, 30000),
127 WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT
, 10),
128 WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER
, 0),
129 WCN36XX_CFG_VAL(TDLS_PUAPSD_MASK
, 0),
130 WCN36XX_CFG_VAL(TDLS_PUAPSD_BUFFER_STA_CAPABLE
, 1),
131 WCN36XX_CFG_VAL(TDLS_PUAPSD_INACTIVITY_TIME
, 0),
132 WCN36XX_CFG_VAL(TDLS_PUAPSD_RX_FRAME_THRESHOLD
, 10),
133 WCN36XX_CFG_VAL(TDLS_OFF_CHANNEL_CAPABLE
, 1),
134 WCN36XX_CFG_VAL(ENABLE_ADAPTIVE_RX_DRAIN
, 1),
135 WCN36XX_CFG_VAL(FLEXCONNECT_POWER_FACTOR
, 0),
136 WCN36XX_CFG_VAL(ANTENNA_DIVERSITY
, 3),
137 WCN36XX_CFG_VAL(ATH_DISABLE
, 0),
138 WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_WLAN_LEN
, 60000),
139 WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_BT_LEN
, 90000),
140 WCN36XX_CFG_VAL(BTC_SAP_STATIC_OPP_ACTIVE_WLAN_LEN
, 30000),
141 WCN36XX_CFG_VAL(BTC_SAP_STATIC_OPP_ACTIVE_BT_LEN
, 30000),
142 WCN36XX_CFG_VAL(ASD_PROBE_INTERVAL
, 50),
143 WCN36XX_CFG_VAL(ASD_TRIGGER_THRESHOLD
, -60),
144 WCN36XX_CFG_VAL(ASD_RTT_RSSI_HYST_THRESHOLD
, 3),
145 WCN36XX_CFG_VAL(BTC_CTS2S_ON_STA_DURING_SCO
, 0),
146 WCN36XX_CFG_VAL(RA_FILTER_ENABLE
, 0),
147 WCN36XX_CFG_VAL(RA_RATE_LIMIT_INTERVAL
, 60),
148 WCN36XX_CFG_VAL(BTC_FATAL_HID_NSNIFF_BLK
, 2),
149 WCN36XX_CFG_VAL(BTC_CRITICAL_HID_NSNIFF_BLK
, 1),
150 WCN36XX_CFG_VAL(BTC_DYN_A2DP_TX_QUEUE_THOLD
, 0),
151 WCN36XX_CFG_VAL(BTC_DYN_OPP_TX_QUEUE_THOLD
, 1),
152 WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_SP
, 10),
153 WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_RX_CNT
, 50),
154 WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_TX_CNT
, 50),
155 WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_TX_CNT_MEAS_WINDOW
, 500),
156 WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_RX_CNT_MEAS_WINDOW
, 500),
157 WCN36XX_CFG_VAL(MAX_PSPOLL_IN_WMM_UAPSD_PS_MODE
, 0),
158 WCN36XX_CFG_VAL(MAX_UAPSD_INACTIVITY_INTERVALS
, 10),
159 WCN36XX_CFG_VAL(ENABLE_DYNAMIC_WMMPS
, 1),
160 WCN36XX_CFG_VAL(BURST_MODE_BE_TXOP_VALUE
, 0),
161 WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE
, 136),
162 WCN36XX_CFG_VAL(BTC_FAST_WLAN_CONN_PREF
, 1),
163 WCN36XX_CFG_VAL(ENABLE_RTSCTS_HTVHT
, 0),
164 WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_WLAN_LEN
, 30000),
165 WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_BT_LEN
, 120000),
166 WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT
, 1000),
167 WCN36XX_CFG_VAL(TOGGLE_ARP_BDRATES
, 0),
168 WCN36XX_CFG_VAL(OPTIMIZE_CA_EVENT
, 0),
169 WCN36XX_CFG_VAL(EXT_SCAN_CONC_MODE
, 0),
170 WCN36XX_CFG_VAL(BAR_WAKEUP_HOST_DISABLE
, 0),
171 WCN36XX_CFG_VAL(SAR_BOFFSET_CORRECTION_ENABLE
, 0),
172 WCN36XX_CFG_VAL(BTC_DISABLE_WLAN_LINK_CRITICAL
, 5),
173 WCN36XX_CFG_VAL(DISABLE_SCAN_DURING_SCO
, 2),
174 WCN36XX_CFG_VAL(CONS_BCNMISS_COUNT
, 0),
175 WCN36XX_CFG_VAL(UNITS_OF_BCN_WAIT_TIME
, 0),
176 WCN36XX_CFG_VAL(TRIGGER_NULLFRAME_BEFORE_HB
, 0),
177 WCN36XX_CFG_VAL(ENABLE_POWERSAVE_OFFLOAD
, 0),
180 static int put_cfg_tlv_u32(struct wcn36xx
*wcn
, size_t *len
, u32 id
, u32 value
)
182 struct wcn36xx_hal_cfg
*entry
;
185 if (*len
+ sizeof(*entry
) + sizeof(u32
) >= WCN36XX_HAL_BUF_SIZE
) {
186 wcn36xx_err("Not enough room for TLV entry\n");
190 entry
= (struct wcn36xx_hal_cfg
*) (wcn
->hal_buf
+ *len
);
192 entry
->len
= sizeof(u32
);
193 entry
->pad_bytes
= 0;
196 val
= (u32
*) (entry
+ 1);
199 *len
+= sizeof(*entry
) + sizeof(u32
);
204 static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx
*wcn
,
205 struct ieee80211_sta
*sta
,
206 struct wcn36xx_hal_config_bss_params
*bss_params
)
208 if (NL80211_BAND_5GHZ
== WCN36XX_BAND(wcn
))
209 bss_params
->nw_type
= WCN36XX_HAL_11A_NW_TYPE
;
210 else if (sta
&& sta
->ht_cap
.ht_supported
)
211 bss_params
->nw_type
= WCN36XX_HAL_11N_NW_TYPE
;
212 else if (sta
&& (sta
->supp_rates
[NL80211_BAND_2GHZ
] & 0x7f))
213 bss_params
->nw_type
= WCN36XX_HAL_11G_NW_TYPE
;
215 bss_params
->nw_type
= WCN36XX_HAL_11B_NW_TYPE
;
218 static inline u8
is_cap_supported(unsigned long caps
, unsigned long flag
)
220 return caps
& flag
? 1 : 0;
223 static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif
*vif
,
224 struct ieee80211_sta
*sta
,
225 struct wcn36xx_hal_config_bss_params
*bss_params
)
227 if (sta
&& sta
->ht_cap
.ht_supported
) {
228 unsigned long caps
= sta
->ht_cap
.cap
;
229 bss_params
->ht
= sta
->ht_cap
.ht_supported
;
230 bss_params
->tx_channel_width_set
= is_cap_supported(caps
,
231 IEEE80211_HT_CAP_SUP_WIDTH_20_40
);
232 bss_params
->lsig_tx_op_protection_full_support
=
233 is_cap_supported(caps
,
234 IEEE80211_HT_CAP_LSIG_TXOP_PROT
);
236 bss_params
->ht_oper_mode
= vif
->bss_conf
.ht_operation_mode
;
237 bss_params
->lln_non_gf_coexist
=
238 !!(vif
->bss_conf
.ht_operation_mode
&
239 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT
);
240 /* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */
241 bss_params
->dual_cts_protection
= 0;
242 /* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */
243 bss_params
->ht20_coexist
= 0;
248 wcn36xx_smd_set_bss_vht_params(struct ieee80211_vif
*vif
,
249 struct ieee80211_sta
*sta
,
250 struct wcn36xx_hal_config_bss_params_v1
*bss
)
252 if (sta
&& sta
->vht_cap
.vht_supported
)
253 bss
->vht_capable
= 1;
256 static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta
*sta
,
257 struct wcn36xx_hal_config_sta_params
*sta_params
)
259 if (sta
->ht_cap
.ht_supported
) {
260 unsigned long caps
= sta
->ht_cap
.cap
;
261 sta_params
->ht_capable
= sta
->ht_cap
.ht_supported
;
262 sta_params
->tx_channel_width_set
= is_cap_supported(caps
,
263 IEEE80211_HT_CAP_SUP_WIDTH_20_40
);
264 sta_params
->lsig_txop_protection
= is_cap_supported(caps
,
265 IEEE80211_HT_CAP_LSIG_TXOP_PROT
);
267 sta_params
->max_ampdu_size
= sta
->ht_cap
.ampdu_factor
;
268 sta_params
->max_ampdu_density
= sta
->ht_cap
.ampdu_density
;
269 sta_params
->max_amsdu_size
= is_cap_supported(caps
,
270 IEEE80211_HT_CAP_MAX_AMSDU
);
271 sta_params
->sgi_20Mhz
= is_cap_supported(caps
,
272 IEEE80211_HT_CAP_SGI_20
);
273 sta_params
->sgi_40mhz
= is_cap_supported(caps
,
274 IEEE80211_HT_CAP_SGI_40
);
275 sta_params
->green_field_capable
= is_cap_supported(caps
,
276 IEEE80211_HT_CAP_GRN_FLD
);
277 sta_params
->delayed_ba_support
= is_cap_supported(caps
,
278 IEEE80211_HT_CAP_DELAY_BA
);
279 sta_params
->dsss_cck_mode_40mhz
= is_cap_supported(caps
,
280 IEEE80211_HT_CAP_DSSSCCK40
);
284 static void wcn36xx_smd_set_sta_vht_params(struct wcn36xx
*wcn
,
285 struct ieee80211_sta
*sta
,
286 struct wcn36xx_hal_config_sta_params_v1
*sta_params
)
288 if (sta
->vht_cap
.vht_supported
) {
289 unsigned long caps
= sta
->vht_cap
.cap
;
291 sta_params
->vht_capable
= sta
->vht_cap
.vht_supported
;
292 sta_params
->vht_ldpc_enabled
=
293 is_cap_supported(caps
, IEEE80211_VHT_CAP_RXLDPC
);
294 if (get_feat_caps(wcn
->fw_feat_caps
, MU_MIMO
)) {
295 sta_params
->vht_tx_mu_beamformee_capable
=
296 is_cap_supported(caps
, IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE
);
297 if (sta_params
->vht_tx_mu_beamformee_capable
)
298 sta_params
->vht_tx_bf_enabled
= 1;
300 sta_params
->vht_tx_mu_beamformee_capable
= 0;
302 sta_params
->vht_tx_channel_width_set
= 0;
306 static void wcn36xx_smd_set_sta_ht_ldpc_params(struct ieee80211_sta
*sta
,
307 struct wcn36xx_hal_config_sta_params_v1
*sta_params
)
309 if (sta
->ht_cap
.ht_supported
) {
310 sta_params
->ht_ldpc_enabled
=
311 is_cap_supported(sta
->ht_cap
.cap
, IEEE80211_HT_CAP_LDPC_CODING
);
315 static void wcn36xx_smd_set_sta_default_ht_params(
316 struct wcn36xx_hal_config_sta_params
*sta_params
)
318 sta_params
->ht_capable
= 1;
319 sta_params
->tx_channel_width_set
= 1;
320 sta_params
->lsig_txop_protection
= 1;
321 sta_params
->max_ampdu_size
= 3;
322 sta_params
->max_ampdu_density
= 5;
323 sta_params
->max_amsdu_size
= 0;
324 sta_params
->sgi_20Mhz
= 1;
325 sta_params
->sgi_40mhz
= 1;
326 sta_params
->green_field_capable
= 1;
327 sta_params
->delayed_ba_support
= 0;
328 sta_params
->dsss_cck_mode_40mhz
= 1;
331 static void wcn36xx_smd_set_sta_default_vht_params(struct wcn36xx
*wcn
,
332 struct wcn36xx_hal_config_sta_params_v1
*sta_params
)
334 if (wcn
->rf_id
== RF_IRIS_WCN3680
) {
335 sta_params
->vht_capable
= 1;
336 sta_params
->vht_tx_mu_beamformee_capable
= 1;
338 sta_params
->vht_capable
= 0;
339 sta_params
->vht_tx_mu_beamformee_capable
= 0;
342 sta_params
->vht_ldpc_enabled
= 0;
343 sta_params
->vht_tx_channel_width_set
= 0;
344 sta_params
->vht_tx_bf_enabled
= 0;
347 static void wcn36xx_smd_set_sta_default_ht_ldpc_params(struct wcn36xx
*wcn
,
348 struct wcn36xx_hal_config_sta_params_v1
*sta_params
)
350 if (wcn
->rf_id
== RF_IRIS_WCN3680
)
351 sta_params
->ht_ldpc_enabled
= 1;
353 sta_params
->ht_ldpc_enabled
= 0;
356 static void wcn36xx_smd_set_sta_params(struct wcn36xx
*wcn
,
357 struct ieee80211_vif
*vif
,
358 struct ieee80211_sta
*sta
,
359 struct wcn36xx_hal_config_sta_params
*sta_params
)
361 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
362 struct wcn36xx_sta
*sta_priv
= NULL
;
363 if (vif
->type
== NL80211_IFTYPE_ADHOC
||
364 vif
->type
== NL80211_IFTYPE_AP
||
365 vif
->type
== NL80211_IFTYPE_MESH_POINT
) {
366 sta_params
->type
= 1;
367 sta_params
->sta_index
= WCN36XX_HAL_STA_INVALID_IDX
;
369 sta_params
->type
= 0;
370 sta_params
->sta_index
= vif_priv
->self_sta_index
;
373 sta_params
->listen_interval
= WCN36XX_LISTEN_INTERVAL(wcn
);
376 * In STA mode ieee80211_sta contains bssid and ieee80211_vif
377 * contains our mac address. In AP mode we are bssid so vif
378 * contains bssid and ieee80211_sta contains mac.
380 if (NL80211_IFTYPE_STATION
== vif
->type
)
381 memcpy(&sta_params
->mac
, vif
->addr
, ETH_ALEN
);
383 memcpy(&sta_params
->bssid
, vif
->addr
, ETH_ALEN
);
385 sta_params
->encrypt_type
= vif_priv
->encrypt_type
;
386 sta_params
->short_preamble_supported
= true;
388 sta_params
->rifs_mode
= 0;
390 sta_params
->action
= 0;
391 sta_params
->uapsd
= 0;
392 sta_params
->mimo_ps
= WCN36XX_HAL_HT_MIMO_PS_STATIC
;
393 sta_params
->max_ampdu_duration
= 0;
394 sta_params
->bssid_index
= vif_priv
->bss_index
;
398 sta_priv
= wcn36xx_sta_to_priv(sta
);
399 if (NL80211_IFTYPE_STATION
== vif
->type
)
400 memcpy(&sta_params
->bssid
, sta
->addr
, ETH_ALEN
);
402 memcpy(&sta_params
->mac
, sta
->addr
, ETH_ALEN
);
403 sta_params
->wmm_enabled
= sta
->wme
;
404 sta_params
->max_sp_len
= sta
->max_sp
;
405 sta_params
->aid
= sta_priv
->aid
;
406 wcn36xx_smd_set_sta_ht_params(sta
, sta_params
);
407 memcpy(&sta_params
->supported_rates
, &sta_priv
->supported_rates
,
408 sizeof(struct wcn36xx_hal_supported_rates
));
410 wcn36xx_set_default_rates((struct wcn36xx_hal_supported_rates
*)
411 &sta_params
->supported_rates
);
412 wcn36xx_smd_set_sta_default_ht_params(sta_params
);
416 static int wcn36xx_smd_send_and_wait(struct wcn36xx
*wcn
, size_t len
)
420 struct wcn36xx_hal_msg_header
*hdr
=
421 (struct wcn36xx_hal_msg_header
*)wcn
->hal_buf
;
422 u16 req_type
= hdr
->msg_type
;
424 wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP
, "HAL >>> ", wcn
->hal_buf
, len
);
426 init_completion(&wcn
->hal_rsp_compl
);
428 ret
= rpmsg_send(wcn
->smd_channel
, wcn
->hal_buf
, len
);
430 wcn36xx_err("HAL TX failed for req %d\n", req_type
);
433 if (wait_for_completion_timeout(&wcn
->hal_rsp_compl
,
434 msecs_to_jiffies(HAL_MSG_TIMEOUT
)) <= 0) {
435 wcn36xx_err("Timeout! No SMD response to req %d in %dms\n",
436 req_type
, HAL_MSG_TIMEOUT
);
440 wcn36xx_dbg(WCN36XX_DBG_SMD
,
441 "SMD command (req %d, rsp %d) completed in %dms\n",
442 req_type
, hdr
->msg_type
,
443 jiffies_to_msecs(jiffies
- start
));
448 static void init_hal_msg(struct wcn36xx_hal_msg_header
*hdr
,
449 enum wcn36xx_hal_host_msg_type msg_type
,
452 memset(hdr
, 0, msg_size
+ sizeof(*hdr
));
453 hdr
->msg_type
= msg_type
;
454 hdr
->msg_version
= WCN36XX_HAL_MSG_VERSION0
;
455 hdr
->len
= msg_size
+ sizeof(*hdr
);
458 #define __INIT_HAL_MSG(msg_body, type, version) \
460 memset(&msg_body, 0, sizeof(msg_body)); \
461 msg_body.header.msg_type = type; \
462 msg_body.header.msg_version = version; \
463 msg_body.header.len = sizeof(msg_body); \
466 #define INIT_HAL_MSG(msg_body, type) \
467 __INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION0)
469 #define INIT_HAL_MSG_V1(msg_body, type) \
470 __INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION1)
472 #define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \
474 memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \
475 p_msg_body->header.msg_type = WCN36XX_HAL_PROCESS_PTT_REQ; \
476 p_msg_body->header.msg_version = WCN36XX_HAL_MSG_VERSION0; \
477 p_msg_body->header.len = sizeof(*p_msg_body) + ppt_msg_len; \
480 #define PREPARE_HAL_BUF(send_buf, msg_body) \
482 memset(send_buf, 0, msg_body.header.len); \
483 memcpy(send_buf, &msg_body, sizeof(msg_body)); \
486 #define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \
488 memset(send_buf, 0, p_msg_body->header.len); \
489 memcpy(send_buf, p_msg_body, p_msg_body->header.len); \
492 static int wcn36xx_smd_rsp_status_check(void *buf
, size_t len
)
494 struct wcn36xx_fw_msg_status_rsp
*rsp
;
496 if (len
< sizeof(struct wcn36xx_hal_msg_header
) +
497 sizeof(struct wcn36xx_fw_msg_status_rsp
))
500 rsp
= (struct wcn36xx_fw_msg_status_rsp
*)
501 (buf
+ sizeof(struct wcn36xx_hal_msg_header
));
503 if (WCN36XX_FW_MSG_RESULT_SUCCESS
!= rsp
->status
)
509 int wcn36xx_smd_load_nv(struct wcn36xx
*wcn
)
511 struct nv_data
*nv_d
;
512 struct wcn36xx_hal_nv_img_download_req_msg msg_body
;
518 ret
= request_firmware(&wcn
->nv
, WLAN_NV_FILE
, wcn
->dev
);
520 wcn36xx_err("Failed to load nv file %s: %d\n",
526 nv_d
= (struct nv_data
*)wcn
->nv
->data
;
527 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_DOWNLOAD_NV_REQ
);
529 msg_body
.header
.len
+= WCN36XX_NV_FRAGMENT_SIZE
;
531 msg_body
.frag_number
= 0;
532 /* hal_buf must be protected with mutex */
533 mutex_lock(&wcn
->hal_mutex
);
536 fw_bytes_left
= wcn
->nv
->size
- fm_offset
- 4;
537 if (fw_bytes_left
> WCN36XX_NV_FRAGMENT_SIZE
) {
538 msg_body
.last_fragment
= 0;
539 msg_body
.nv_img_buffer_size
= WCN36XX_NV_FRAGMENT_SIZE
;
541 msg_body
.last_fragment
= 1;
542 msg_body
.nv_img_buffer_size
= fw_bytes_left
;
544 /* Do not forget update general message len */
545 msg_body
.header
.len
= sizeof(msg_body
) + fw_bytes_left
;
549 /* Add load NV request message header */
550 memcpy(wcn
->hal_buf
, &msg_body
, sizeof(msg_body
));
552 /* Add NV body itself */
553 memcpy(wcn
->hal_buf
+ sizeof(msg_body
),
554 &nv_d
->table
+ fm_offset
,
555 msg_body
.nv_img_buffer_size
);
557 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
560 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
,
563 wcn36xx_err("hal_load_nv response failed err=%d\n",
567 msg_body
.frag_number
++;
568 fm_offset
+= WCN36XX_NV_FRAGMENT_SIZE
;
570 } while (msg_body
.last_fragment
!= 1);
573 mutex_unlock(&wcn
->hal_mutex
);
577 static int wcn36xx_smd_start_rsp(struct wcn36xx
*wcn
, void *buf
, size_t len
)
579 struct wcn36xx_hal_mac_start_rsp_msg
*rsp
;
581 if (len
< sizeof(*rsp
))
584 rsp
= (struct wcn36xx_hal_mac_start_rsp_msg
*)buf
;
586 if (WCN36XX_FW_MSG_RESULT_SUCCESS
!= rsp
->start_rsp_params
.status
)
589 memcpy(wcn
->crm_version
, rsp
->start_rsp_params
.crm_version
,
590 WCN36XX_HAL_VERSION_LENGTH
);
591 memcpy(wcn
->wlan_version
, rsp
->start_rsp_params
.wlan_version
,
592 WCN36XX_HAL_VERSION_LENGTH
);
594 /* null terminate the strings, just in case */
595 wcn
->crm_version
[WCN36XX_HAL_VERSION_LENGTH
] = '\0';
596 wcn
->wlan_version
[WCN36XX_HAL_VERSION_LENGTH
] = '\0';
598 wcn
->fw_revision
= rsp
->start_rsp_params
.version
.revision
;
599 wcn
->fw_version
= rsp
->start_rsp_params
.version
.version
;
600 wcn
->fw_minor
= rsp
->start_rsp_params
.version
.minor
;
601 wcn
->fw_major
= rsp
->start_rsp_params
.version
.major
;
603 if (wcn
->first_boot
) {
604 wcn
->first_boot
= false;
605 wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n",
606 wcn
->wlan_version
, wcn
->crm_version
);
608 wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n",
609 wcn
->fw_major
, wcn
->fw_minor
,
610 wcn
->fw_version
, wcn
->fw_revision
,
611 rsp
->start_rsp_params
.stations
,
612 rsp
->start_rsp_params
.bssids
);
617 int wcn36xx_smd_start(struct wcn36xx
*wcn
)
619 struct wcn36xx_hal_mac_start_req_msg msg_body
, *body
;
624 static struct wcn36xx_cfg_val
*cfg_vals
;
626 mutex_lock(&wcn
->hal_mutex
);
627 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_START_REQ
);
629 msg_body
.params
.type
= DRIVER_TYPE_PRODUCTION
;
630 msg_body
.params
.len
= 0;
632 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
634 body
= (struct wcn36xx_hal_mac_start_req_msg
*)wcn
->hal_buf
;
635 len
= body
->header
.len
;
637 if (wcn
->rf_id
== RF_IRIS_WCN3680
) {
638 cfg_vals
= wcn3680_cfg_vals
;
639 cfg_elements
= ARRAY_SIZE(wcn3680_cfg_vals
);
641 cfg_vals
= wcn36xx_cfg_vals
;
642 cfg_elements
= ARRAY_SIZE(wcn36xx_cfg_vals
);
645 for (i
= 0; i
< cfg_elements
; i
++) {
646 ret
= put_cfg_tlv_u32(wcn
, &len
, cfg_vals
[i
].cfg_id
,
651 body
->header
.len
= len
;
652 body
->params
.len
= len
- sizeof(*body
);
654 wcn36xx_dbg(WCN36XX_DBG_HAL
, "hal start type %d\n",
655 msg_body
.params
.type
);
657 ret
= wcn36xx_smd_send_and_wait(wcn
, body
->header
.len
);
659 wcn36xx_err("Sending hal_start failed\n");
663 ret
= wcn36xx_smd_start_rsp(wcn
, wcn
->hal_buf
, wcn
->hal_rsp_len
);
665 wcn36xx_err("hal_start response failed err=%d\n", ret
);
670 mutex_unlock(&wcn
->hal_mutex
);
674 int wcn36xx_smd_stop(struct wcn36xx
*wcn
)
676 struct wcn36xx_hal_mac_stop_req_msg msg_body
;
679 mutex_lock(&wcn
->hal_mutex
);
680 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_STOP_REQ
);
682 msg_body
.stop_req_params
.reason
= HAL_STOP_TYPE_RF_KILL
;
684 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
686 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
688 wcn36xx_err("Sending hal_stop failed\n");
691 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
693 wcn36xx_err("hal_stop response failed err=%d\n", ret
);
697 mutex_unlock(&wcn
->hal_mutex
);
701 int wcn36xx_smd_init_scan(struct wcn36xx
*wcn
, enum wcn36xx_hal_sys_mode mode
,
702 struct ieee80211_vif
*vif
)
704 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
705 struct wcn36xx_hal_init_scan_req_msg msg_body
;
708 mutex_lock(&wcn
->hal_mutex
);
709 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_INIT_SCAN_REQ
);
711 msg_body
.mode
= mode
;
712 if (vif_priv
->bss_index
!= WCN36XX_HAL_BSS_INVALID_IDX
) {
713 /* Notify BSSID with null DATA packet */
714 msg_body
.frame_type
= 2;
716 msg_body
.scan_entry
.bss_index
[0] = vif_priv
->bss_index
;
717 msg_body
.scan_entry
.active_bss_count
= 1;
720 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
722 wcn36xx_dbg(WCN36XX_DBG_HAL
, "hal init scan mode %d\n", msg_body
.mode
);
724 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
726 wcn36xx_err("Sending hal_init_scan failed\n");
729 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
731 wcn36xx_err("hal_init_scan response failed err=%d\n", ret
);
735 mutex_unlock(&wcn
->hal_mutex
);
739 int wcn36xx_smd_start_scan(struct wcn36xx
*wcn
, u8 scan_channel
)
741 struct wcn36xx_hal_start_scan_req_msg msg_body
;
744 mutex_lock(&wcn
->hal_mutex
);
745 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_START_SCAN_REQ
);
747 msg_body
.scan_channel
= scan_channel
;
749 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
751 wcn36xx_dbg(WCN36XX_DBG_HAL
, "hal start scan channel %d\n",
752 msg_body
.scan_channel
);
754 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
756 wcn36xx_err("Sending hal_start_scan failed\n");
759 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
761 wcn36xx_err("hal_start_scan response failed err=%d\n", ret
);
765 mutex_unlock(&wcn
->hal_mutex
);
769 int wcn36xx_smd_end_scan(struct wcn36xx
*wcn
, u8 scan_channel
)
771 struct wcn36xx_hal_end_scan_req_msg msg_body
;
774 mutex_lock(&wcn
->hal_mutex
);
775 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_END_SCAN_REQ
);
777 msg_body
.scan_channel
= scan_channel
;
779 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
781 wcn36xx_dbg(WCN36XX_DBG_HAL
, "hal end scan channel %d\n",
782 msg_body
.scan_channel
);
784 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
786 wcn36xx_err("Sending hal_end_scan failed\n");
789 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
791 wcn36xx_err("hal_end_scan response failed err=%d\n", ret
);
795 mutex_unlock(&wcn
->hal_mutex
);
799 int wcn36xx_smd_finish_scan(struct wcn36xx
*wcn
,
800 enum wcn36xx_hal_sys_mode mode
,
801 struct ieee80211_vif
*vif
)
803 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
804 struct wcn36xx_hal_finish_scan_req_msg msg_body
;
807 mutex_lock(&wcn
->hal_mutex
);
808 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_FINISH_SCAN_REQ
);
810 msg_body
.mode
= mode
;
811 msg_body
.oper_channel
= WCN36XX_HW_CHANNEL(wcn
);
812 if (vif_priv
->bss_index
!= WCN36XX_HAL_BSS_INVALID_IDX
) {
813 /* Notify BSSID with null data packet */
815 msg_body
.frame_type
= 2;
816 msg_body
.scan_entry
.bss_index
[0] = vif_priv
->bss_index
;
817 msg_body
.scan_entry
.active_bss_count
= 1;
820 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
822 wcn36xx_dbg(WCN36XX_DBG_HAL
, "hal finish scan mode %d\n",
825 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
827 wcn36xx_err("Sending hal_finish_scan failed\n");
830 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
832 wcn36xx_err("hal_finish_scan response failed err=%d\n", ret
);
836 mutex_unlock(&wcn
->hal_mutex
);
840 int wcn36xx_smd_start_hw_scan(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
,
841 struct cfg80211_scan_request
*req
)
843 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
844 struct wcn36xx_hal_start_scan_offload_req_msg
*msg_body
;
847 if (req
->ie_len
> WCN36XX_MAX_SCAN_IE_LEN
)
850 mutex_lock(&wcn
->hal_mutex
);
851 msg_body
= kzalloc(sizeof(*msg_body
), GFP_KERNEL
);
857 INIT_HAL_MSG((*msg_body
), WCN36XX_HAL_START_SCAN_OFFLOAD_REQ
);
859 msg_body
->scan_type
= WCN36XX_HAL_SCAN_TYPE_ACTIVE
;
860 msg_body
->min_ch_time
= 30;
861 msg_body
->max_ch_time
= 100;
862 msg_body
->scan_hidden
= 1;
863 memcpy(msg_body
->mac
, vif
->addr
, ETH_ALEN
);
864 msg_body
->bss_type
= vif_priv
->bss_type
;
865 msg_body
->p2p_search
= vif
->p2p
;
867 msg_body
->num_ssid
= min_t(u8
, req
->n_ssids
, ARRAY_SIZE(msg_body
->ssids
));
868 for (i
= 0; i
< msg_body
->num_ssid
; i
++) {
869 msg_body
->ssids
[i
].length
= min_t(u8
, req
->ssids
[i
].ssid_len
,
870 sizeof(msg_body
->ssids
[i
].ssid
));
871 memcpy(msg_body
->ssids
[i
].ssid
, req
->ssids
[i
].ssid
,
872 msg_body
->ssids
[i
].length
);
875 msg_body
->num_channel
= min_t(u8
, req
->n_channels
,
876 sizeof(msg_body
->channels
));
877 for (i
= 0; i
< msg_body
->num_channel
; i
++) {
878 msg_body
->channels
[i
] =
879 HW_VALUE_CHANNEL(req
->channels
[i
]->hw_value
);
882 msg_body
->header
.len
-= WCN36XX_MAX_SCAN_IE_LEN
;
884 if (req
->ie_len
> 0) {
885 msg_body
->ie_len
= req
->ie_len
;
886 msg_body
->header
.len
+= req
->ie_len
;
887 memcpy(msg_body
->ie
, req
->ie
, req
->ie_len
);
890 PREPARE_HAL_BUF(wcn
->hal_buf
, (*msg_body
));
892 wcn36xx_dbg(WCN36XX_DBG_HAL
,
893 "hal start hw-scan (channels: %u; ssids: %u; p2p: %s)\n",
894 msg_body
->num_channel
, msg_body
->num_ssid
,
895 msg_body
->p2p_search
? "yes" : "no");
897 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
->header
.len
);
899 wcn36xx_err("Sending hal_start_scan_offload failed\n");
902 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
904 wcn36xx_err("hal_start_scan_offload response failed err=%d\n",
910 mutex_unlock(&wcn
->hal_mutex
);
914 int wcn36xx_smd_stop_hw_scan(struct wcn36xx
*wcn
)
916 struct wcn36xx_hal_stop_scan_offload_req_msg msg_body
;
919 mutex_lock(&wcn
->hal_mutex
);
920 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_STOP_SCAN_OFFLOAD_REQ
);
921 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
923 wcn36xx_dbg(WCN36XX_DBG_HAL
, "hal stop hw-scan\n");
925 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
927 wcn36xx_err("Sending hal_stop_scan_offload failed\n");
930 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
932 wcn36xx_err("hal_stop_scan_offload response failed err=%d\n",
937 mutex_unlock(&wcn
->hal_mutex
);
941 static int wcn36xx_smd_switch_channel_rsp(void *buf
, size_t len
)
943 struct wcn36xx_hal_switch_channel_rsp_msg
*rsp
;
946 ret
= wcn36xx_smd_rsp_status_check(buf
, len
);
949 rsp
= (struct wcn36xx_hal_switch_channel_rsp_msg
*)buf
;
950 wcn36xx_dbg(WCN36XX_DBG_HAL
, "channel switched to: %d, status: %d\n",
951 rsp
->channel_number
, rsp
->status
);
955 int wcn36xx_smd_switch_channel(struct wcn36xx
*wcn
,
956 struct ieee80211_vif
*vif
, int ch
)
958 struct wcn36xx_hal_switch_channel_req_msg msg_body
;
961 mutex_lock(&wcn
->hal_mutex
);
962 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_CH_SWITCH_REQ
);
964 msg_body
.channel_number
= (u8
)ch
;
965 msg_body
.tx_mgmt_power
= 0xbf;
966 msg_body
.max_tx_power
= 0xbf;
967 memcpy(msg_body
.self_sta_mac_addr
, vif
->addr
, ETH_ALEN
);
969 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
971 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
973 wcn36xx_err("Sending hal_switch_channel failed\n");
976 ret
= wcn36xx_smd_switch_channel_rsp(wcn
->hal_buf
, wcn
->hal_rsp_len
);
978 wcn36xx_err("hal_switch_channel response failed err=%d\n", ret
);
982 mutex_unlock(&wcn
->hal_mutex
);
986 static int wcn36xx_smd_process_ptt_msg_rsp(void *buf
, size_t len
,
987 void **p_ptt_rsp_msg
)
989 struct wcn36xx_hal_process_ptt_msg_rsp_msg
*rsp
;
992 ret
= wcn36xx_smd_rsp_status_check(buf
, len
);
996 rsp
= (struct wcn36xx_hal_process_ptt_msg_rsp_msg
*)buf
;
998 wcn36xx_dbg(WCN36XX_DBG_HAL
, "process ptt msg responded with length %d\n",
1000 wcn36xx_dbg_dump(WCN36XX_DBG_HAL_DUMP
, "HAL_PTT_MSG_RSP:", rsp
->ptt_msg
,
1001 rsp
->header
.len
- sizeof(rsp
->ptt_msg_resp_status
));
1003 if (rsp
->header
.len
> 0) {
1004 *p_ptt_rsp_msg
= kmemdup(rsp
->ptt_msg
, rsp
->header
.len
,
1006 if (!*p_ptt_rsp_msg
)
1012 int wcn36xx_smd_process_ptt_msg(struct wcn36xx
*wcn
,
1013 struct ieee80211_vif
*vif
, void *ptt_msg
, size_t len
,
1016 struct wcn36xx_hal_process_ptt_msg_req_msg
*p_msg_body
;
1019 mutex_lock(&wcn
->hal_mutex
);
1020 p_msg_body
= kmalloc(
1021 sizeof(struct wcn36xx_hal_process_ptt_msg_req_msg
) + len
,
1027 INIT_HAL_PTT_MSG(p_msg_body
, len
);
1029 memcpy(&p_msg_body
->ptt_msg
, ptt_msg
, len
);
1031 PREPARE_HAL_PTT_MSG_BUF(wcn
->hal_buf
, p_msg_body
);
1033 ret
= wcn36xx_smd_send_and_wait(wcn
, p_msg_body
->header
.len
);
1035 wcn36xx_err("Sending hal_process_ptt_msg failed\n");
1038 ret
= wcn36xx_smd_process_ptt_msg_rsp(wcn
->hal_buf
, wcn
->hal_rsp_len
,
1041 wcn36xx_err("process_ptt_msg response failed err=%d\n", ret
);
1047 mutex_unlock(&wcn
->hal_mutex
);
1051 static int wcn36xx_smd_update_scan_params_rsp(void *buf
, size_t len
)
1053 struct wcn36xx_hal_update_scan_params_resp
*rsp
;
1055 rsp
= (struct wcn36xx_hal_update_scan_params_resp
*)buf
;
1057 /* Remove the PNO version bit */
1058 rsp
->status
&= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK
));
1060 if (WCN36XX_FW_MSG_RESULT_SUCCESS
!= rsp
->status
) {
1061 wcn36xx_warn("error response from update scan\n");
1068 int wcn36xx_smd_update_scan_params(struct wcn36xx
*wcn
,
1069 u8
*channels
, size_t channel_count
)
1071 struct wcn36xx_hal_update_scan_params_req_ex msg_body
;
1074 mutex_lock(&wcn
->hal_mutex
);
1075 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ
);
1077 msg_body
.dot11d_enabled
= false;
1078 msg_body
.dot11d_resolved
= true;
1080 msg_body
.channel_count
= channel_count
;
1081 memcpy(msg_body
.channels
, channels
, channel_count
);
1082 msg_body
.active_min_ch_time
= 60;
1083 msg_body
.active_max_ch_time
= 120;
1084 msg_body
.passive_min_ch_time
= 60;
1085 msg_body
.passive_max_ch_time
= 110;
1086 msg_body
.state
= PHY_SINGLE_CHANNEL_CENTERED
;
1088 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
1090 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1091 "hal update scan params channel_count %d\n",
1092 msg_body
.channel_count
);
1094 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1096 wcn36xx_err("Sending hal_update_scan_params failed\n");
1099 ret
= wcn36xx_smd_update_scan_params_rsp(wcn
->hal_buf
,
1102 wcn36xx_err("hal_update_scan_params response failed err=%d\n",
1107 mutex_unlock(&wcn
->hal_mutex
);
1111 static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx
*wcn
,
1112 struct ieee80211_vif
*vif
,
1116 struct wcn36xx_hal_add_sta_self_rsp_msg
*rsp
;
1117 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
1119 if (len
< sizeof(*rsp
))
1122 rsp
= (struct wcn36xx_hal_add_sta_self_rsp_msg
*)buf
;
1124 if (rsp
->status
!= WCN36XX_FW_MSG_RESULT_SUCCESS
) {
1125 wcn36xx_warn("hal add sta self failure: %d\n",
1130 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1131 "hal add sta self status %d self_sta_index %d dpu_index %d\n",
1132 rsp
->status
, rsp
->self_sta_index
, rsp
->dpu_index
);
1134 vif_priv
->self_sta_index
= rsp
->self_sta_index
;
1135 vif_priv
->self_dpu_desc_index
= rsp
->dpu_index
;
1140 int wcn36xx_smd_add_sta_self(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
)
1142 struct wcn36xx_hal_add_sta_self_req msg_body
;
1145 mutex_lock(&wcn
->hal_mutex
);
1146 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_ADD_STA_SELF_REQ
);
1148 memcpy(&msg_body
.self_addr
, vif
->addr
, ETH_ALEN
);
1150 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
1152 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1153 "hal add sta self self_addr %pM status %d\n",
1154 msg_body
.self_addr
, msg_body
.status
);
1156 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1158 wcn36xx_err("Sending hal_add_sta_self failed\n");
1161 ret
= wcn36xx_smd_add_sta_self_rsp(wcn
,
1166 wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret
);
1170 mutex_unlock(&wcn
->hal_mutex
);
1174 int wcn36xx_smd_delete_sta_self(struct wcn36xx
*wcn
, u8
*addr
)
1176 struct wcn36xx_hal_del_sta_self_req_msg msg_body
;
1179 mutex_lock(&wcn
->hal_mutex
);
1180 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_DEL_STA_SELF_REQ
);
1182 memcpy(&msg_body
.self_addr
, addr
, ETH_ALEN
);
1184 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
1186 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1188 wcn36xx_err("Sending hal_delete_sta_self failed\n");
1191 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
1193 wcn36xx_err("hal_delete_sta_self response failed err=%d\n",
1198 mutex_unlock(&wcn
->hal_mutex
);
1202 int wcn36xx_smd_delete_sta(struct wcn36xx
*wcn
, u8 sta_index
)
1204 struct wcn36xx_hal_delete_sta_req_msg msg_body
;
1207 mutex_lock(&wcn
->hal_mutex
);
1208 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_DELETE_STA_REQ
);
1210 msg_body
.sta_index
= sta_index
;
1212 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
1214 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1215 "hal delete sta sta_index %d\n",
1216 msg_body
.sta_index
);
1218 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1220 wcn36xx_err("Sending hal_delete_sta failed\n");
1223 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
1225 wcn36xx_err("hal_delete_sta response failed err=%d\n", ret
);
1229 mutex_unlock(&wcn
->hal_mutex
);
1233 static int wcn36xx_smd_join_rsp(void *buf
, size_t len
)
1235 struct wcn36xx_hal_join_rsp_msg
*rsp
;
1237 if (wcn36xx_smd_rsp_status_check(buf
, len
))
1240 rsp
= (struct wcn36xx_hal_join_rsp_msg
*)buf
;
1242 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1243 "hal rsp join status %d tx_mgmt_power %d\n",
1244 rsp
->status
, rsp
->tx_mgmt_power
);
1249 int wcn36xx_smd_join(struct wcn36xx
*wcn
, const u8
*bssid
, u8
*vif
, u8 ch
)
1251 struct wcn36xx_hal_join_req_msg msg_body
;
1254 mutex_lock(&wcn
->hal_mutex
);
1255 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_JOIN_REQ
);
1257 memcpy(&msg_body
.bssid
, bssid
, ETH_ALEN
);
1258 memcpy(&msg_body
.self_sta_mac_addr
, vif
, ETH_ALEN
);
1259 msg_body
.channel
= ch
;
1261 if (conf_is_ht40_minus(&wcn
->hw
->conf
))
1262 msg_body
.secondary_channel_offset
=
1263 PHY_DOUBLE_CHANNEL_HIGH_PRIMARY
;
1264 else if (conf_is_ht40_plus(&wcn
->hw
->conf
))
1265 msg_body
.secondary_channel_offset
=
1266 PHY_DOUBLE_CHANNEL_LOW_PRIMARY
;
1268 msg_body
.secondary_channel_offset
=
1269 PHY_SINGLE_CHANNEL_CENTERED
;
1271 msg_body
.link_state
= WCN36XX_HAL_LINK_PREASSOC_STATE
;
1273 msg_body
.max_tx_power
= 0xbf;
1274 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
1276 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1277 "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n",
1278 msg_body
.bssid
, msg_body
.self_sta_mac_addr
,
1279 msg_body
.channel
, msg_body
.link_state
);
1281 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1283 wcn36xx_err("Sending hal_join failed\n");
1286 ret
= wcn36xx_smd_join_rsp(wcn
->hal_buf
, wcn
->hal_rsp_len
);
1288 wcn36xx_err("hal_join response failed err=%d\n", ret
);
1292 mutex_unlock(&wcn
->hal_mutex
);
1296 int wcn36xx_smd_set_link_st(struct wcn36xx
*wcn
, const u8
*bssid
,
1298 enum wcn36xx_hal_link_state state
)
1300 struct wcn36xx_hal_set_link_state_req_msg msg_body
;
1303 mutex_lock(&wcn
->hal_mutex
);
1304 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_SET_LINK_ST_REQ
);
1306 memcpy(&msg_body
.bssid
, bssid
, ETH_ALEN
);
1307 memcpy(&msg_body
.self_mac_addr
, sta_mac
, ETH_ALEN
);
1308 msg_body
.state
= state
;
1310 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
1312 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1313 "hal set link state bssid %pM self_mac_addr %pM state %d\n",
1314 msg_body
.bssid
, msg_body
.self_mac_addr
, msg_body
.state
);
1316 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1318 wcn36xx_err("Sending hal_set_link_st failed\n");
1321 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
1323 wcn36xx_err("hal_set_link_st response failed err=%d\n", ret
);
1327 mutex_unlock(&wcn
->hal_mutex
);
1331 static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx
*wcn
,
1332 const struct wcn36xx_hal_config_sta_params
*orig
,
1333 struct wcn36xx_hal_config_sta_params_v1
*v1
)
1335 /* convert orig to v1 format */
1336 memcpy(&v1
->bssid
, orig
->bssid
, ETH_ALEN
);
1337 memcpy(&v1
->mac
, orig
->mac
, ETH_ALEN
);
1338 v1
->aid
= orig
->aid
;
1339 v1
->type
= orig
->type
;
1340 v1
->short_preamble_supported
= orig
->short_preamble_supported
;
1341 v1
->listen_interval
= orig
->listen_interval
;
1342 v1
->wmm_enabled
= orig
->wmm_enabled
;
1343 v1
->ht_capable
= orig
->ht_capable
;
1344 v1
->tx_channel_width_set
= orig
->tx_channel_width_set
;
1345 v1
->rifs_mode
= orig
->rifs_mode
;
1346 v1
->lsig_txop_protection
= orig
->lsig_txop_protection
;
1347 v1
->max_ampdu_size
= orig
->max_ampdu_size
;
1348 v1
->max_ampdu_density
= orig
->max_ampdu_density
;
1349 v1
->sgi_40mhz
= orig
->sgi_40mhz
;
1350 v1
->sgi_20Mhz
= orig
->sgi_20Mhz
;
1351 v1
->rmf
= orig
->rmf
;
1352 v1
->encrypt_type
= orig
->encrypt_type
;
1353 v1
->action
= orig
->action
;
1354 v1
->uapsd
= orig
->uapsd
;
1355 v1
->max_sp_len
= orig
->max_sp_len
;
1356 v1
->green_field_capable
= orig
->green_field_capable
;
1357 v1
->mimo_ps
= orig
->mimo_ps
;
1358 v1
->delayed_ba_support
= orig
->delayed_ba_support
;
1359 v1
->max_ampdu_duration
= orig
->max_ampdu_duration
;
1360 v1
->dsss_cck_mode_40mhz
= orig
->dsss_cck_mode_40mhz
;
1361 memcpy(&v1
->supported_rates
, &orig
->supported_rates
,
1362 sizeof(orig
->supported_rates
));
1363 v1
->sta_index
= orig
->sta_index
;
1364 v1
->bssid_index
= orig
->bssid_index
;
1365 v1
->p2p
= orig
->p2p
;
1369 wcn36xx_smd_set_sta_params_v1(struct wcn36xx
*wcn
,
1370 struct ieee80211_vif
*vif
,
1371 struct ieee80211_sta
*sta
,
1372 struct wcn36xx_hal_config_sta_params_v1
*sta_par
)
1374 struct wcn36xx_sta
*sta_priv
= NULL
;
1375 struct wcn36xx_hal_config_sta_params sta_par_v0
;
1377 wcn36xx_smd_set_sta_params(wcn
, vif
, sta
, &sta_par_v0
);
1378 wcn36xx_smd_convert_sta_to_v1(wcn
, &sta_par_v0
, sta_par
);
1381 sta_priv
= wcn36xx_sta_to_priv(sta
);
1382 wcn36xx_smd_set_sta_vht_params(wcn
, sta
, sta_par
);
1383 wcn36xx_smd_set_sta_ht_ldpc_params(sta
, sta_par
);
1384 memcpy(&sta_par
->supported_rates
, &sta_priv
->supported_rates
,
1385 sizeof(sta_par
->supported_rates
));
1387 wcn36xx_set_default_rates_v1(&sta_par
->supported_rates
);
1388 wcn36xx_smd_set_sta_default_vht_params(wcn
, sta_par
);
1389 wcn36xx_smd_set_sta_default_ht_ldpc_params(wcn
, sta_par
);
1393 static int wcn36xx_smd_config_sta_rsp(struct wcn36xx
*wcn
,
1394 struct ieee80211_sta
*sta
,
1398 struct wcn36xx_hal_config_sta_rsp_msg
*rsp
;
1399 struct config_sta_rsp_params
*params
;
1400 struct wcn36xx_sta
*sta_priv
= wcn36xx_sta_to_priv(sta
);
1402 if (len
< sizeof(*rsp
))
1405 rsp
= (struct wcn36xx_hal_config_sta_rsp_msg
*)buf
;
1406 params
= &rsp
->params
;
1408 if (params
->status
!= WCN36XX_FW_MSG_RESULT_SUCCESS
) {
1409 wcn36xx_warn("hal config sta response failure: %d\n",
1414 sta_priv
->sta_index
= params
->sta_index
;
1415 sta_priv
->dpu_desc_index
= params
->dpu_index
;
1416 sta_priv
->ucast_dpu_sign
= params
->uc_ucast_sig
;
1418 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1419 "hal config sta rsp status %d sta_index %d bssid_index %d uc_ucast_sig %d p2p %d\n",
1420 params
->status
, params
->sta_index
, params
->bssid_index
,
1421 params
->uc_ucast_sig
, params
->p2p
);
1426 static int wcn36xx_smd_config_sta_v1(struct wcn36xx
*wcn
,
1427 struct ieee80211_vif
*vif
,
1428 struct ieee80211_sta
*sta
)
1430 struct wcn36xx_hal_config_sta_req_msg_v1 msg_body
;
1431 struct wcn36xx_hal_config_sta_params_v1
*sta_params
;
1433 if (wcn
->rf_id
== RF_IRIS_WCN3680
) {
1434 INIT_HAL_MSG_V1(msg_body
, WCN36XX_HAL_CONFIG_STA_REQ
);
1436 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_CONFIG_STA_REQ
);
1437 msg_body
.header
.len
-= WCN36XX_DIFF_STA_PARAMS_V1_NOVHT
;
1440 sta_params
= &msg_body
.sta_params
;
1442 wcn36xx_smd_set_sta_params_v1(wcn
, vif
, sta
, sta_params
);
1444 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
1446 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1447 "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1448 sta_params
->action
, sta_params
->sta_index
, sta_params
->bssid_index
,
1449 sta_params
->bssid
, sta_params
->type
, sta_params
->mac
, sta_params
->aid
);
1451 return wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1454 static int wcn36xx_smd_config_sta_v0(struct wcn36xx
*wcn
,
1455 struct ieee80211_vif
*vif
,
1456 struct ieee80211_sta
*sta
)
1458 struct wcn36xx_hal_config_sta_req_msg msg
;
1459 struct wcn36xx_hal_config_sta_params
*sta_params
;
1461 INIT_HAL_MSG(msg
, WCN36XX_HAL_CONFIG_STA_REQ
);
1463 sta_params
= &msg
.sta_params
;
1465 wcn36xx_smd_set_sta_params(wcn
, vif
, sta
, sta_params
);
1467 PREPARE_HAL_BUF(wcn
->hal_buf
, msg
);
1469 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1470 "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
1471 sta_params
->action
, sta_params
->sta_index
,
1472 sta_params
->bssid_index
, sta_params
->bssid
,
1473 sta_params
->type
, sta_params
->mac
, sta_params
->aid
);
1475 return wcn36xx_smd_send_and_wait(wcn
, msg
.header
.len
);
1478 int wcn36xx_smd_config_sta(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
,
1479 struct ieee80211_sta
*sta
)
1483 mutex_lock(&wcn
->hal_mutex
);
1485 if (!wcn36xx_is_fw_version(wcn
, 1, 2, 2, 24))
1486 ret
= wcn36xx_smd_config_sta_v1(wcn
, vif
, sta
);
1488 ret
= wcn36xx_smd_config_sta_v0(wcn
, vif
, sta
);
1491 wcn36xx_err("Sending hal_config_sta failed\n");
1494 ret
= wcn36xx_smd_config_sta_rsp(wcn
,
1499 wcn36xx_err("hal_config_sta response failed err=%d\n", ret
);
1503 mutex_unlock(&wcn
->hal_mutex
);
1507 static void wcn36xx_smd_set_bss_params(struct wcn36xx
*wcn
,
1508 struct ieee80211_vif
*vif
,
1509 struct ieee80211_sta
*sta
,
1512 struct wcn36xx_hal_config_bss_params
*bss
)
1514 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
1516 WARN_ON(is_zero_ether_addr(bssid
));
1518 memcpy(&bss
->bssid
, bssid
, ETH_ALEN
);
1520 memcpy(bss
->self_mac_addr
, vif
->addr
, ETH_ALEN
);
1522 if (vif
->type
== NL80211_IFTYPE_STATION
) {
1523 bss
->bss_type
= WCN36XX_HAL_INFRASTRUCTURE_MODE
;
1527 bss
->wcn36xx_hal_persona
= WCN36XX_HAL_STA_MODE
;
1528 } else if (vif
->type
== NL80211_IFTYPE_AP
||
1529 vif
->type
== NL80211_IFTYPE_MESH_POINT
) {
1530 bss
->bss_type
= WCN36XX_HAL_INFRA_AP_MODE
;
1534 bss
->wcn36xx_hal_persona
= WCN36XX_HAL_STA_SAP_MODE
;
1535 } else if (vif
->type
== NL80211_IFTYPE_ADHOC
) {
1536 bss
->bss_type
= WCN36XX_HAL_IBSS_MODE
;
1541 wcn36xx_warn("Unknown type for bss config: %d\n", vif
->type
);
1544 if (vif
->type
== NL80211_IFTYPE_STATION
)
1545 wcn36xx_smd_set_bss_nw_type(wcn
, sta
, bss
);
1547 bss
->nw_type
= WCN36XX_HAL_11N_NW_TYPE
;
1549 bss
->short_slot_time_supported
= vif
->bss_conf
.use_short_slot
;
1550 bss
->lla_coexist
= 0;
1551 bss
->llb_coexist
= 0;
1552 bss
->llg_coexist
= 0;
1554 bss
->beacon_interval
= vif
->bss_conf
.beacon_int
;
1555 bss
->dtim_period
= vif_priv
->dtim_period
;
1557 wcn36xx_smd_set_bss_ht_params(vif
, sta
, bss
);
1559 bss
->oper_channel
= WCN36XX_HW_CHANNEL(wcn
);
1561 if (conf_is_ht40_minus(&wcn
->hw
->conf
))
1562 bss
->ext_channel
= IEEE80211_HT_PARAM_CHA_SEC_BELOW
;
1563 else if (conf_is_ht40_plus(&wcn
->hw
->conf
))
1564 bss
->ext_channel
= IEEE80211_HT_PARAM_CHA_SEC_ABOVE
;
1566 bss
->ext_channel
= IEEE80211_HT_PARAM_CHA_SEC_NONE
;
1570 /* wcn->ssid is only valid in AP and IBSS mode */
1571 bss
->ssid
.length
= vif_priv
->ssid
.length
;
1572 memcpy(bss
->ssid
.ssid
, vif_priv
->ssid
.ssid
, vif_priv
->ssid
.length
);
1574 bss
->obss_prot_enabled
= 0;
1576 bss
->max_probe_resp_retry_limit
= 0;
1577 bss
->hidden_ssid
= vif
->bss_conf
.hidden_ssid
;
1578 bss
->proxy_probe_resp
= 0;
1579 bss
->edca_params_valid
= 0;
1581 /* FIXME: set acbe, acbk, acvi and acvo */
1583 bss
->ext_set_sta_key_param_valid
= 0;
1585 /* FIXME: set ext_set_sta_key_param */
1587 bss
->spectrum_mgt_enable
= 0;
1588 bss
->tx_mgmt_power
= 0;
1589 bss
->max_tx_power
= WCN36XX_MAX_POWER(wcn
);
1590 bss
->action
= update
;
1592 vif_priv
->bss_type
= bss
->bss_type
;
1595 static int wcn36xx_smd_config_bss_v1(struct wcn36xx
*wcn
,
1596 struct ieee80211_vif
*vif
,
1597 struct ieee80211_sta
*sta_80211
,
1601 struct wcn36xx_hal_config_bss_req_msg_v1
*msg_body
;
1602 struct wcn36xx_hal_config_bss_params_v1
*bss
;
1603 struct wcn36xx_hal_config_bss_params bss_v0
;
1604 struct wcn36xx_hal_config_sta_params_v1
*sta
;
1605 struct cfg80211_chan_def
*chandef
;
1608 msg_body
= kzalloc(sizeof(*msg_body
), GFP_KERNEL
);
1612 if (wcn
->rf_id
== RF_IRIS_WCN3680
) {
1613 INIT_HAL_MSG_V1((*msg_body
), WCN36XX_HAL_CONFIG_BSS_REQ
);
1615 INIT_HAL_MSG((*msg_body
), WCN36XX_HAL_CONFIG_BSS_REQ
);
1616 msg_body
->header
.len
-= WCN36XX_DIFF_BSS_PARAMS_V1_NOVHT
;
1619 bss
= &msg_body
->bss_params
;
1622 memset(&bss_v0
, 0x00, sizeof(bss_v0
));
1623 wcn36xx_smd_set_bss_params(wcn
, vif
, sta_80211
, bssid
, update
, &bss_v0
);
1624 wcn36xx_smd_set_sta_params_v1(wcn
, vif
, sta_80211
, sta
);
1626 /* convert orig to v1 */
1627 memcpy(bss
->bssid
, &bss_v0
.bssid
, ETH_ALEN
);
1628 memcpy(bss
->self_mac_addr
, &bss_v0
.self_mac_addr
, ETH_ALEN
);
1630 bss
->bss_type
= bss_v0
.bss_type
;
1631 bss
->oper_mode
= bss_v0
.oper_mode
;
1632 bss
->nw_type
= bss_v0
.nw_type
;
1634 bss
->short_slot_time_supported
=
1635 bss_v0
.short_slot_time_supported
;
1636 bss
->lla_coexist
= bss_v0
.lla_coexist
;
1637 bss
->llb_coexist
= bss_v0
.llb_coexist
;
1638 bss
->llg_coexist
= bss_v0
.llg_coexist
;
1639 bss
->ht20_coexist
= bss_v0
.ht20_coexist
;
1640 bss
->lln_non_gf_coexist
= bss_v0
.lln_non_gf_coexist
;
1642 bss
->lsig_tx_op_protection_full_support
=
1643 bss_v0
.lsig_tx_op_protection_full_support
;
1644 bss
->rifs_mode
= bss_v0
.rifs_mode
;
1645 bss
->beacon_interval
= bss_v0
.beacon_interval
;
1646 bss
->dtim_period
= bss_v0
.dtim_period
;
1647 bss
->tx_channel_width_set
= bss_v0
.tx_channel_width_set
;
1648 bss
->oper_channel
= bss_v0
.oper_channel
;
1650 if (wcn
->hw
->conf
.chandef
.width
== NL80211_CHAN_WIDTH_80
) {
1651 chandef
= &wcn
->hw
->conf
.chandef
;
1652 bss
->ext_channel
= HW_VALUE_PHY(chandef
->chan
->hw_value
);
1654 bss
->ext_channel
= bss_v0
.ext_channel
;
1657 bss
->reserved
= bss_v0
.reserved
;
1659 memcpy(&bss
->ssid
, &bss_v0
.ssid
,
1660 sizeof(bss_v0
.ssid
));
1662 bss
->action
= bss_v0
.action
;
1663 bss
->rateset
= bss_v0
.rateset
;
1664 bss
->ht
= bss_v0
.ht
;
1665 bss
->obss_prot_enabled
= bss_v0
.obss_prot_enabled
;
1666 bss
->rmf
= bss_v0
.rmf
;
1667 bss
->ht_oper_mode
= bss_v0
.ht_oper_mode
;
1668 bss
->dual_cts_protection
= bss_v0
.dual_cts_protection
;
1670 bss
->max_probe_resp_retry_limit
=
1671 bss_v0
.max_probe_resp_retry_limit
;
1672 bss
->hidden_ssid
= bss_v0
.hidden_ssid
;
1673 bss
->proxy_probe_resp
= bss_v0
.proxy_probe_resp
;
1674 bss
->edca_params_valid
= bss_v0
.edca_params_valid
;
1676 memcpy(&bss
->acbe
, &bss_v0
.acbe
,
1677 sizeof(bss_v0
.acbe
));
1678 memcpy(&bss
->acbk
, &bss_v0
.acbk
,
1679 sizeof(bss_v0
.acbk
));
1680 memcpy(&bss
->acvi
, &bss_v0
.acvi
,
1681 sizeof(bss_v0
.acvi
));
1682 memcpy(&bss
->acvo
, &bss_v0
.acvo
,
1683 sizeof(bss_v0
.acvo
));
1685 bss
->ext_set_sta_key_param_valid
=
1686 bss_v0
.ext_set_sta_key_param_valid
;
1688 memcpy(&bss
->ext_set_sta_key_param
,
1689 &bss_v0
.ext_set_sta_key_param
,
1690 sizeof(bss_v0
.acvo
));
1692 bss
->wcn36xx_hal_persona
= bss_v0
.wcn36xx_hal_persona
;
1693 bss
->spectrum_mgt_enable
= bss_v0
.spectrum_mgt_enable
;
1694 bss
->tx_mgmt_power
= bss_v0
.tx_mgmt_power
;
1695 bss
->max_tx_power
= bss_v0
.max_tx_power
;
1697 wcn36xx_smd_set_bss_vht_params(vif
, sta_80211
, bss
);
1699 PREPARE_HAL_BUF(wcn
->hal_buf
, (*msg_body
));
1701 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1702 "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1703 bss
->bssid
, bss
->self_mac_addr
, bss
->bss_type
,
1704 bss
->oper_mode
, bss
->nw_type
);
1706 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1707 "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1708 sta
->bssid
, sta
->action
, sta
->sta_index
,
1709 sta
->bssid_index
, sta
->aid
, sta
->type
, sta
->mac
);
1711 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
->header
.len
);
1717 static int wcn36xx_smd_config_bss_v0(struct wcn36xx
*wcn
,
1718 struct ieee80211_vif
*vif
,
1719 struct ieee80211_sta
*sta
,
1723 struct wcn36xx_hal_config_bss_req_msg
*msg
;
1724 struct wcn36xx_hal_config_bss_params
*bss
;
1725 struct wcn36xx_hal_config_sta_params
*sta_params
;
1728 msg
= kzalloc(sizeof(*msg
), GFP_KERNEL
);
1732 INIT_HAL_MSG((*msg
), WCN36XX_HAL_CONFIG_BSS_REQ
);
1734 bss
= &msg
->bss_params
;
1735 sta_params
= &bss
->sta
;
1737 wcn36xx_smd_set_bss_params(wcn
, vif
, sta
, bssid
, update
, bss
);
1738 wcn36xx_smd_set_sta_params(wcn
, vif
, sta
, sta_params
);
1740 PREPARE_HAL_BUF(wcn
->hal_buf
, (*msg
));
1742 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1743 "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1744 bss
->bssid
, bss
->self_mac_addr
, bss
->bss_type
,
1745 bss
->oper_mode
, bss
->nw_type
);
1747 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1748 "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1749 sta_params
->bssid
, sta_params
->action
,
1750 sta_params
->sta_index
, sta_params
->bssid_index
,
1751 sta_params
->aid
, sta_params
->type
,
1754 ret
= wcn36xx_smd_send_and_wait(wcn
, msg
->header
.len
);
1760 static int wcn36xx_smd_config_bss_rsp(struct wcn36xx
*wcn
,
1761 struct ieee80211_vif
*vif
,
1762 struct ieee80211_sta
*sta
,
1766 struct wcn36xx_hal_config_bss_rsp_msg
*rsp
;
1767 struct wcn36xx_hal_config_bss_rsp_params
*params
;
1768 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
1770 if (len
< sizeof(*rsp
))
1773 rsp
= (struct wcn36xx_hal_config_bss_rsp_msg
*)buf
;
1774 params
= &rsp
->bss_rsp_params
;
1776 if (params
->status
!= WCN36XX_FW_MSG_RESULT_SUCCESS
) {
1777 wcn36xx_warn("hal config bss response failure: %d\n",
1782 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1783 "hal config bss rsp status %d bss_idx %d dpu_desc_index %d"
1784 " sta_idx %d self_idx %d bcast_idx %d mac %pM"
1785 " power %d ucast_dpu_signature %d\n",
1786 params
->status
, params
->bss_index
, params
->dpu_desc_index
,
1787 params
->bss_sta_index
, params
->bss_self_sta_index
,
1788 params
->bss_bcast_sta_idx
, params
->mac
,
1789 params
->tx_mgmt_power
, params
->ucast_dpu_signature
);
1791 vif_priv
->bss_index
= params
->bss_index
;
1794 struct wcn36xx_sta
*sta_priv
= wcn36xx_sta_to_priv(sta
);
1795 sta_priv
->bss_sta_index
= params
->bss_sta_index
;
1796 sta_priv
->bss_dpu_desc_index
= params
->dpu_desc_index
;
1799 vif_priv
->self_ucast_dpu_sign
= params
->ucast_dpu_signature
;
1804 int wcn36xx_smd_config_bss(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
,
1805 struct ieee80211_sta
*sta
, const u8
*bssid
,
1810 mutex_lock(&wcn
->hal_mutex
);
1812 if (!wcn36xx_is_fw_version(wcn
, 1, 2, 2, 24))
1813 ret
= wcn36xx_smd_config_bss_v1(wcn
, vif
, sta
, bssid
, update
);
1815 ret
= wcn36xx_smd_config_bss_v0(wcn
, vif
, sta
, bssid
, update
);
1818 wcn36xx_err("Sending hal_config_bss failed\n");
1821 ret
= wcn36xx_smd_config_bss_rsp(wcn
,
1827 wcn36xx_err("hal_config_bss response failed err=%d\n", ret
);
1830 mutex_unlock(&wcn
->hal_mutex
);
1834 int wcn36xx_smd_delete_bss(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
)
1836 struct wcn36xx_hal_delete_bss_req_msg msg_body
;
1837 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
1840 mutex_lock(&wcn
->hal_mutex
);
1842 if (vif_priv
->bss_index
== WCN36XX_HAL_BSS_INVALID_IDX
)
1845 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_DELETE_BSS_REQ
);
1847 msg_body
.bss_index
= vif_priv
->bss_index
;
1849 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
1851 wcn36xx_dbg(WCN36XX_DBG_HAL
, "hal delete bss %d\n", msg_body
.bss_index
);
1853 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1855 wcn36xx_err("Sending hal_delete_bss failed\n");
1858 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
1860 wcn36xx_err("hal_delete_bss response failed err=%d\n", ret
);
1864 vif_priv
->bss_index
= WCN36XX_HAL_BSS_INVALID_IDX
;
1866 mutex_unlock(&wcn
->hal_mutex
);
1870 int wcn36xx_smd_send_beacon(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
,
1871 struct sk_buff
*skb_beacon
, u16 tim_off
,
1874 struct wcn36xx_hal_send_beacon_req_msg msg_body
;
1875 int ret
, pad
, pvm_len
;
1877 mutex_lock(&wcn
->hal_mutex
);
1878 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_SEND_BEACON_REQ
);
1880 pvm_len
= skb_beacon
->data
[tim_off
+ 1] - 3;
1881 pad
= TIM_MIN_PVM_SIZE
- pvm_len
;
1883 /* Padding is irrelevant to mesh mode since tim_off is always 0. */
1884 if (vif
->type
== NL80211_IFTYPE_MESH_POINT
)
1887 msg_body
.beacon_length
= skb_beacon
->len
+ pad
;
1888 /* TODO need to find out why + 6 is needed */
1889 msg_body
.beacon_length6
= msg_body
.beacon_length
+ 6;
1891 if (msg_body
.beacon_length
> BEACON_TEMPLATE_SIZE
) {
1892 wcn36xx_err("Beacon is too big: beacon size=%d\n",
1893 msg_body
.beacon_length
);
1897 memcpy(msg_body
.beacon
, skb_beacon
->data
, skb_beacon
->len
);
1898 memcpy(msg_body
.bssid
, vif
->addr
, ETH_ALEN
);
1902 * The wcn36xx FW has a fixed size for the PVM in the TIM. If
1903 * given the beacon template from mac80211 with a PVM shorter
1904 * than the FW expectes it will overwrite the data after the
1907 wcn36xx_dbg(WCN36XX_DBG_HAL
, "Pad TIM PVM. %d bytes at %d\n",
1909 memmove(&msg_body
.beacon
[tim_off
+ 5 + pvm_len
+ pad
],
1910 &msg_body
.beacon
[tim_off
+ 5 + pvm_len
],
1911 skb_beacon
->len
- (tim_off
+ 5 + pvm_len
));
1912 memset(&msg_body
.beacon
[tim_off
+ 5 + pvm_len
], 0, pad
);
1913 msg_body
.beacon
[tim_off
+ 1] += pad
;
1916 /* TODO need to find out why this is needed? */
1917 if (vif
->type
== NL80211_IFTYPE_MESH_POINT
)
1918 /* mesh beacon don't need this, so push further down */
1919 msg_body
.tim_ie_offset
= 256;
1921 msg_body
.tim_ie_offset
= tim_off
+4;
1922 msg_body
.p2p_ie_offset
= p2p_off
;
1923 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
1925 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1926 "hal send beacon beacon_length %d\n",
1927 msg_body
.beacon_length
);
1929 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
1931 wcn36xx_err("Sending hal_send_beacon failed\n");
1934 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
1936 wcn36xx_err("hal_send_beacon response failed err=%d\n", ret
);
1940 mutex_unlock(&wcn
->hal_mutex
);
1944 int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx
*wcn
,
1945 struct ieee80211_vif
*vif
,
1946 struct sk_buff
*skb
)
1948 struct wcn36xx_hal_send_probe_resp_req_msg msg
;
1951 mutex_lock(&wcn
->hal_mutex
);
1952 INIT_HAL_MSG(msg
, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ
);
1954 if (skb
->len
> BEACON_TEMPLATE_SIZE
) {
1955 wcn36xx_warn("probe response template is too big: %d\n",
1961 msg
.probe_resp_template_len
= skb
->len
;
1962 memcpy(&msg
.probe_resp_template
, skb
->data
, skb
->len
);
1964 memcpy(msg
.bssid
, vif
->addr
, ETH_ALEN
);
1966 PREPARE_HAL_BUF(wcn
->hal_buf
, msg
);
1968 wcn36xx_dbg(WCN36XX_DBG_HAL
,
1969 "hal update probe rsp len %d bssid %pM\n",
1970 msg
.probe_resp_template_len
, msg
.bssid
);
1972 ret
= wcn36xx_smd_send_and_wait(wcn
, msg
.header
.len
);
1974 wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n");
1977 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
1979 wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n",
1984 mutex_unlock(&wcn
->hal_mutex
);
1988 int wcn36xx_smd_set_stakey(struct wcn36xx
*wcn
,
1989 enum ani_ed_type enc_type
,
1995 struct wcn36xx_hal_set_sta_key_req_msg msg_body
;
1998 mutex_lock(&wcn
->hal_mutex
);
1999 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_SET_STAKEY_REQ
);
2001 msg_body
.set_sta_key_params
.sta_index
= sta_index
;
2002 msg_body
.set_sta_key_params
.enc_type
= enc_type
;
2004 if (enc_type
== WCN36XX_HAL_ED_WEP104
||
2005 enc_type
== WCN36XX_HAL_ED_WEP40
) {
2006 /* Use bss key for wep (static) */
2007 msg_body
.set_sta_key_params
.def_wep_idx
= keyidx
;
2008 msg_body
.set_sta_key_params
.wep_type
= 0;
2010 msg_body
.set_sta_key_params
.key
[0].id
= keyidx
;
2011 msg_body
.set_sta_key_params
.key
[0].unicast
= 1;
2012 msg_body
.set_sta_key_params
.key
[0].direction
= WCN36XX_HAL_TX_RX
;
2013 msg_body
.set_sta_key_params
.key
[0].pae_role
= 0;
2014 msg_body
.set_sta_key_params
.key
[0].length
= keylen
;
2015 memcpy(msg_body
.set_sta_key_params
.key
[0].key
, key
, keylen
);
2018 msg_body
.set_sta_key_params
.single_tid_rc
= 1;
2020 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2022 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2024 wcn36xx_err("Sending hal_set_stakey failed\n");
2027 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2029 wcn36xx_err("hal_set_stakey response failed err=%d\n", ret
);
2033 mutex_unlock(&wcn
->hal_mutex
);
2037 int wcn36xx_smd_set_bsskey(struct wcn36xx
*wcn
,
2038 enum ani_ed_type enc_type
,
2044 struct wcn36xx_hal_set_bss_key_req_msg msg_body
;
2047 mutex_lock(&wcn
->hal_mutex
);
2048 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_SET_BSSKEY_REQ
);
2049 msg_body
.bss_idx
= bssidx
;
2050 msg_body
.enc_type
= enc_type
;
2051 msg_body
.num_keys
= 1;
2052 msg_body
.keys
[0].id
= keyidx
;
2053 msg_body
.keys
[0].unicast
= 0;
2054 msg_body
.keys
[0].direction
= WCN36XX_HAL_RX_ONLY
;
2055 msg_body
.keys
[0].pae_role
= 0;
2056 msg_body
.keys
[0].length
= keylen
;
2057 memcpy(msg_body
.keys
[0].key
, key
, keylen
);
2059 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2061 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2063 wcn36xx_err("Sending hal_set_bsskey failed\n");
2066 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2068 wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret
);
2072 mutex_unlock(&wcn
->hal_mutex
);
2076 int wcn36xx_smd_remove_stakey(struct wcn36xx
*wcn
,
2077 enum ani_ed_type enc_type
,
2081 struct wcn36xx_hal_remove_sta_key_req_msg msg_body
;
2084 mutex_lock(&wcn
->hal_mutex
);
2085 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_RMV_STAKEY_REQ
);
2087 msg_body
.sta_idx
= sta_index
;
2088 msg_body
.enc_type
= enc_type
;
2089 msg_body
.key_id
= keyidx
;
2091 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2093 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2095 wcn36xx_err("Sending hal_remove_stakey failed\n");
2098 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2100 wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret
);
2104 mutex_unlock(&wcn
->hal_mutex
);
2108 int wcn36xx_smd_remove_bsskey(struct wcn36xx
*wcn
,
2109 enum ani_ed_type enc_type
,
2113 struct wcn36xx_hal_remove_bss_key_req_msg msg_body
;
2116 mutex_lock(&wcn
->hal_mutex
);
2117 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_RMV_BSSKEY_REQ
);
2118 msg_body
.bss_idx
= bssidx
;
2119 msg_body
.enc_type
= enc_type
;
2120 msg_body
.key_id
= keyidx
;
2122 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2124 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2126 wcn36xx_err("Sending hal_remove_bsskey failed\n");
2129 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2131 wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret
);
2135 mutex_unlock(&wcn
->hal_mutex
);
2139 int wcn36xx_smd_enter_bmps(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
)
2141 struct wcn36xx_hal_enter_bmps_req_msg msg_body
;
2142 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
2145 mutex_lock(&wcn
->hal_mutex
);
2146 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_ENTER_BMPS_REQ
);
2148 msg_body
.bss_index
= vif_priv
->bss_index
;
2149 msg_body
.tbtt
= vif
->bss_conf
.sync_tsf
;
2150 msg_body
.dtim_period
= vif_priv
->dtim_period
;
2152 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2154 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2156 wcn36xx_err("Sending hal_enter_bmps failed\n");
2159 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2161 wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret
);
2165 mutex_unlock(&wcn
->hal_mutex
);
2169 int wcn36xx_smd_exit_bmps(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
)
2171 struct wcn36xx_hal_exit_bmps_req_msg msg_body
;
2172 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
2175 mutex_lock(&wcn
->hal_mutex
);
2176 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_EXIT_BMPS_REQ
);
2178 msg_body
.bss_index
= vif_priv
->bss_index
;
2179 msg_body
.send_data_null
= 1;
2181 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2183 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2185 wcn36xx_err("Sending hal_exit_bmps failed\n");
2188 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2190 wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret
);
2194 mutex_unlock(&wcn
->hal_mutex
);
2198 int wcn36xx_smd_set_power_params(struct wcn36xx
*wcn
, bool ignore_dtim
)
2200 struct wcn36xx_hal_set_power_params_req_msg msg_body
;
2203 mutex_lock(&wcn
->hal_mutex
);
2204 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_SET_POWER_PARAMS_REQ
);
2207 * When host is down ignore every second dtim
2210 msg_body
.ignore_dtim
= 1;
2211 msg_body
.dtim_period
= 2;
2213 msg_body
.listen_interval
= WCN36XX_LISTEN_INTERVAL(wcn
);
2215 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2217 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2219 wcn36xx_err("Sending hal_set_power_params failed\n");
2224 mutex_unlock(&wcn
->hal_mutex
);
2228 /* Notice: This function should be called after associated, or else it
2231 int wcn36xx_smd_keep_alive_req(struct wcn36xx
*wcn
,
2232 struct ieee80211_vif
*vif
,
2235 struct wcn36xx_hal_keep_alive_req_msg msg_body
;
2236 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
2239 mutex_lock(&wcn
->hal_mutex
);
2240 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_KEEP_ALIVE_REQ
);
2242 if (packet_type
== WCN36XX_HAL_KEEP_ALIVE_NULL_PKT
) {
2243 msg_body
.bss_index
= vif_priv
->bss_index
;
2244 msg_body
.packet_type
= WCN36XX_HAL_KEEP_ALIVE_NULL_PKT
;
2245 msg_body
.time_period
= WCN36XX_KEEP_ALIVE_TIME_PERIOD
;
2246 } else if (packet_type
== WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP
) {
2247 /* TODO: it also support ARP response type */
2249 wcn36xx_warn("unknown keep alive packet type %d\n", packet_type
);
2254 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2256 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2258 wcn36xx_err("Sending hal_keep_alive failed\n");
2261 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2263 wcn36xx_err("hal_keep_alive response failed err=%d\n", ret
);
2267 mutex_unlock(&wcn
->hal_mutex
);
2271 int wcn36xx_smd_dump_cmd_req(struct wcn36xx
*wcn
, u32 arg1
, u32 arg2
,
2272 u32 arg3
, u32 arg4
, u32 arg5
)
2274 struct wcn36xx_hal_dump_cmd_req_msg msg_body
;
2277 mutex_lock(&wcn
->hal_mutex
);
2278 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_DUMP_COMMAND_REQ
);
2280 msg_body
.arg1
= arg1
;
2281 msg_body
.arg2
= arg2
;
2282 msg_body
.arg3
= arg3
;
2283 msg_body
.arg4
= arg4
;
2284 msg_body
.arg5
= arg5
;
2286 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2288 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2290 wcn36xx_err("Sending hal_dump_cmd failed\n");
2293 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2295 wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret
);
2299 mutex_unlock(&wcn
->hal_mutex
);
2303 void set_feat_caps(u32
*bitmap
, enum place_holder_in_cap_bitmap cap
)
2305 int arr_idx
, bit_idx
;
2307 if (cap
< 0 || cap
> 127) {
2308 wcn36xx_warn("error cap idx %d\n", cap
);
2314 bitmap
[arr_idx
] |= (1 << bit_idx
);
2317 int get_feat_caps(u32
*bitmap
, enum place_holder_in_cap_bitmap cap
)
2319 int arr_idx
, bit_idx
;
2321 if (cap
< 0 || cap
> 127) {
2322 wcn36xx_warn("error cap idx %d\n", cap
);
2329 return (bitmap
[arr_idx
] & (1 << bit_idx
)) ? 1 : 0;
2332 void clear_feat_caps(u32
*bitmap
, enum place_holder_in_cap_bitmap cap
)
2334 int arr_idx
, bit_idx
;
2336 if (cap
< 0 || cap
> 127) {
2337 wcn36xx_warn("error cap idx %d\n", cap
);
2343 bitmap
[arr_idx
] &= ~(1 << bit_idx
);
2346 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx
*wcn
)
2348 struct wcn36xx_hal_feat_caps_msg msg_body
, *rsp
;
2351 mutex_lock(&wcn
->hal_mutex
);
2352 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ
);
2354 set_feat_caps(msg_body
.feat_caps
, STA_POWERSAVE
);
2355 if (wcn
->rf_id
== RF_IRIS_WCN3680
)
2356 set_feat_caps(msg_body
.feat_caps
, DOT11AC
);
2358 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2360 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2362 wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
2365 if (wcn
->hal_rsp_len
!= sizeof(*rsp
)) {
2366 wcn36xx_err("Invalid hal_feature_caps_exchange response");
2370 rsp
= (struct wcn36xx_hal_feat_caps_msg
*) wcn
->hal_buf
;
2372 for (i
= 0; i
< WCN36XX_HAL_CAPS_SIZE
; i
++)
2373 wcn
->fw_feat_caps
[i
] = rsp
->feat_caps
[i
];
2375 mutex_unlock(&wcn
->hal_mutex
);
2379 static int wcn36xx_smd_add_ba_session_rsp(void *buf
, int len
, u8
*session
)
2381 struct wcn36xx_hal_add_ba_session_rsp_msg
*rsp
;
2383 if (len
< sizeof(*rsp
))
2386 rsp
= (struct wcn36xx_hal_add_ba_session_rsp_msg
*)buf
;
2387 if (rsp
->status
!= WCN36XX_FW_MSG_RESULT_SUCCESS
)
2390 *session
= rsp
->ba_session_id
;
2395 int wcn36xx_smd_add_ba_session(struct wcn36xx
*wcn
,
2396 struct ieee80211_sta
*sta
,
2402 struct wcn36xx_hal_add_ba_session_req_msg msg_body
;
2406 mutex_lock(&wcn
->hal_mutex
);
2407 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_ADD_BA_SESSION_REQ
);
2409 msg_body
.sta_index
= sta_index
;
2410 memcpy(&msg_body
.mac_addr
, sta
->addr
, ETH_ALEN
);
2411 msg_body
.dialog_token
= 0x10;
2414 /* Immediate BA because Delayed BA is not supported */
2415 msg_body
.policy
= 1;
2416 msg_body
.buffer_size
= WCN36XX_AGGR_BUFFER_SIZE
;
2417 msg_body
.timeout
= 0;
2419 msg_body
.ssn
= *ssn
;
2420 msg_body
.direction
= direction
;
2422 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2424 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2426 wcn36xx_err("Sending hal_add_ba_session failed\n");
2429 ret
= wcn36xx_smd_add_ba_session_rsp(wcn
->hal_buf
, wcn
->hal_rsp_len
,
2432 wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret
);
2438 mutex_unlock(&wcn
->hal_mutex
);
2442 int wcn36xx_smd_add_ba(struct wcn36xx
*wcn
, u8 session_id
)
2444 struct wcn36xx_hal_add_ba_req_msg msg_body
;
2447 mutex_lock(&wcn
->hal_mutex
);
2448 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_ADD_BA_REQ
);
2450 msg_body
.session_id
= session_id
;
2451 msg_body
.win_size
= WCN36XX_AGGR_BUFFER_SIZE
;
2453 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2455 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2457 wcn36xx_err("Sending hal_add_ba failed\n");
2460 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2462 wcn36xx_err("hal_add_ba response failed err=%d\n", ret
);
2466 mutex_unlock(&wcn
->hal_mutex
);
2470 int wcn36xx_smd_del_ba(struct wcn36xx
*wcn
, u16 tid
, u8 sta_index
)
2472 struct wcn36xx_hal_del_ba_req_msg msg_body
;
2475 mutex_lock(&wcn
->hal_mutex
);
2476 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_DEL_BA_REQ
);
2478 msg_body
.sta_index
= sta_index
;
2480 msg_body
.direction
= 0;
2481 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2483 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2485 wcn36xx_err("Sending hal_del_ba failed\n");
2488 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2490 wcn36xx_err("hal_del_ba response failed err=%d\n", ret
);
2494 mutex_unlock(&wcn
->hal_mutex
);
2498 static int wcn36xx_smd_trigger_ba_rsp(void *buf
, int len
)
2500 struct wcn36xx_hal_trigger_ba_rsp_msg
*rsp
;
2502 if (len
< sizeof(*rsp
))
2505 rsp
= (struct wcn36xx_hal_trigger_ba_rsp_msg
*) buf
;
2509 int wcn36xx_smd_trigger_ba(struct wcn36xx
*wcn
, u8 sta_index
, u16 tid
, u8 session_id
)
2511 struct wcn36xx_hal_trigger_ba_req_msg msg_body
;
2512 struct wcn36xx_hal_trigger_ba_req_candidate
*candidate
;
2515 mutex_lock(&wcn
->hal_mutex
);
2516 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_TRIGGER_BA_REQ
);
2518 msg_body
.session_id
= session_id
;
2519 msg_body
.candidate_cnt
= 1;
2520 msg_body
.header
.len
+= sizeof(*candidate
);
2521 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2523 candidate
= (struct wcn36xx_hal_trigger_ba_req_candidate
*)
2524 (wcn
->hal_buf
+ sizeof(msg_body
));
2525 candidate
->sta_index
= sta_index
;
2526 candidate
->tid_bitmap
= 1 << tid
;
2528 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
.header
.len
);
2530 wcn36xx_err("Sending hal_trigger_ba failed\n");
2533 ret
= wcn36xx_smd_trigger_ba_rsp(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2535 wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret
);
2539 mutex_unlock(&wcn
->hal_mutex
);
2543 static int wcn36xx_smd_tx_compl_ind(struct wcn36xx
*wcn
, void *buf
, size_t len
)
2545 struct wcn36xx_hal_tx_compl_ind_msg
*rsp
= buf
;
2547 if (len
!= sizeof(*rsp
)) {
2548 wcn36xx_warn("Bad TX complete indication\n");
2552 wcn36xx_dxe_tx_ack_ind(wcn
, rsp
->status
);
2557 static int wcn36xx_smd_hw_scan_ind(struct wcn36xx
*wcn
, void *buf
, size_t len
)
2559 struct wcn36xx_hal_scan_offload_ind
*rsp
= buf
;
2560 struct cfg80211_scan_info scan_info
= {};
2562 if (len
!= sizeof(*rsp
)) {
2563 wcn36xx_warn("Corrupted delete scan indication\n");
2567 wcn36xx_dbg(WCN36XX_DBG_HAL
, "scan indication (type %x)\n", rsp
->type
);
2569 switch (rsp
->type
) {
2570 case WCN36XX_HAL_SCAN_IND_FAILED
:
2571 case WCN36XX_HAL_SCAN_IND_DEQUEUED
:
2572 scan_info
.aborted
= true;
2574 case WCN36XX_HAL_SCAN_IND_COMPLETED
:
2575 mutex_lock(&wcn
->scan_lock
);
2576 wcn
->scan_req
= NULL
;
2577 if (wcn
->scan_aborted
)
2578 scan_info
.aborted
= true;
2579 mutex_unlock(&wcn
->scan_lock
);
2580 ieee80211_scan_completed(wcn
->hw
, &scan_info
);
2582 case WCN36XX_HAL_SCAN_IND_STARTED
:
2583 case WCN36XX_HAL_SCAN_IND_FOREIGN_CHANNEL
:
2584 case WCN36XX_HAL_SCAN_IND_PREEMPTED
:
2585 case WCN36XX_HAL_SCAN_IND_RESTARTED
:
2588 wcn36xx_warn("Unknown scan indication type %x\n", rsp
->type
);
2594 static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx
*wcn
,
2598 struct wcn36xx_hal_missed_beacon_ind_msg
*rsp
= buf
;
2599 struct ieee80211_vif
*vif
= NULL
;
2600 struct wcn36xx_vif
*tmp
;
2602 /* Old FW does not have bss index */
2603 if (wcn36xx_is_fw_version(wcn
, 1, 2, 2, 24)) {
2604 list_for_each_entry(tmp
, &wcn
->vif_list
, list
) {
2605 wcn36xx_dbg(WCN36XX_DBG_HAL
, "beacon missed bss_index %d\n",
2607 vif
= wcn36xx_priv_to_vif(tmp
);
2608 ieee80211_connection_loss(vif
);
2613 if (len
!= sizeof(*rsp
)) {
2614 wcn36xx_warn("Corrupted missed beacon indication\n");
2618 list_for_each_entry(tmp
, &wcn
->vif_list
, list
) {
2619 if (tmp
->bss_index
== rsp
->bss_index
) {
2620 wcn36xx_dbg(WCN36XX_DBG_HAL
, "beacon missed bss_index %d\n",
2622 vif
= wcn36xx_priv_to_vif(tmp
);
2623 ieee80211_connection_loss(vif
);
2628 wcn36xx_warn("BSS index %d not found\n", rsp
->bss_index
);
2632 static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx
*wcn
,
2636 struct wcn36xx_hal_delete_sta_context_ind_msg
*rsp
= buf
;
2637 struct wcn36xx_vif
*tmp
;
2638 struct ieee80211_sta
*sta
;
2640 if (len
!= sizeof(*rsp
)) {
2641 wcn36xx_warn("Corrupted delete sta indication\n");
2645 wcn36xx_dbg(WCN36XX_DBG_HAL
, "delete station indication %pM index %d\n",
2646 rsp
->addr2
, rsp
->sta_id
);
2648 list_for_each_entry(tmp
, &wcn
->vif_list
, list
) {
2650 sta
= ieee80211_find_sta(wcn36xx_priv_to_vif(tmp
), rsp
->addr2
);
2652 ieee80211_report_low_ack(sta
, 0);
2658 wcn36xx_warn("STA with addr %pM and index %d not found\n",
2664 static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx
*wcn
,
2668 struct wcn36xx_hal_print_reg_info_ind
*rsp
= buf
;
2671 if (len
< sizeof(*rsp
)) {
2672 wcn36xx_warn("Corrupted print reg info indication\n");
2676 wcn36xx_dbg(WCN36XX_DBG_HAL
,
2677 "reginfo indication, scenario: 0x%x reason: 0x%x\n",
2678 rsp
->scenario
, rsp
->reason
);
2680 for (i
= 0; i
< rsp
->count
; i
++) {
2681 wcn36xx_dbg(WCN36XX_DBG_HAL
, "\t0x%x: 0x%x\n",
2682 rsp
->regs
[i
].addr
, rsp
->regs
[i
].value
);
2688 int wcn36xx_smd_update_cfg(struct wcn36xx
*wcn
, u32 cfg_id
, u32 value
)
2690 struct wcn36xx_hal_update_cfg_req_msg msg_body
, *body
;
2694 mutex_lock(&wcn
->hal_mutex
);
2695 INIT_HAL_MSG(msg_body
, WCN36XX_HAL_UPDATE_CFG_REQ
);
2697 PREPARE_HAL_BUF(wcn
->hal_buf
, msg_body
);
2699 body
= (struct wcn36xx_hal_update_cfg_req_msg
*) wcn
->hal_buf
;
2700 len
= msg_body
.header
.len
;
2702 put_cfg_tlv_u32(wcn
, &len
, cfg_id
, value
);
2703 body
->header
.len
= len
;
2704 body
->len
= len
- sizeof(*body
);
2706 ret
= wcn36xx_smd_send_and_wait(wcn
, body
->header
.len
);
2708 wcn36xx_err("Sending hal_update_cfg failed\n");
2711 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2713 wcn36xx_err("hal_update_cfg response failed err=%d\n", ret
);
2717 mutex_unlock(&wcn
->hal_mutex
);
2721 int wcn36xx_smd_set_mc_list(struct wcn36xx
*wcn
,
2722 struct ieee80211_vif
*vif
,
2723 struct wcn36xx_hal_rcv_flt_mc_addr_list_type
*fp
)
2725 struct wcn36xx_vif
*vif_priv
= wcn36xx_vif_to_priv(vif
);
2726 struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg
*msg_body
= NULL
;
2729 mutex_lock(&wcn
->hal_mutex
);
2731 msg_body
= (struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg
*)
2733 init_hal_msg(&msg_body
->header
, WCN36XX_HAL_8023_MULTICAST_LIST_REQ
,
2734 sizeof(msg_body
->mc_addr_list
));
2736 /* An empty list means all mc traffic will be received */
2738 memcpy(&msg_body
->mc_addr_list
, fp
,
2739 sizeof(msg_body
->mc_addr_list
));
2741 msg_body
->mc_addr_list
.mc_addr_count
= 0;
2743 msg_body
->mc_addr_list
.bss_index
= vif_priv
->bss_index
;
2745 ret
= wcn36xx_smd_send_and_wait(wcn
, msg_body
->header
.len
);
2747 wcn36xx_err("Sending HAL_8023_MULTICAST_LIST failed\n");
2750 ret
= wcn36xx_smd_rsp_status_check(wcn
->hal_buf
, wcn
->hal_rsp_len
);
2752 wcn36xx_err("HAL_8023_MULTICAST_LIST rsp failed err=%d\n", ret
);
2756 mutex_unlock(&wcn
->hal_mutex
);
2760 int wcn36xx_smd_rsp_process(struct rpmsg_device
*rpdev
,
2761 void *buf
, int len
, void *priv
, u32 addr
)
2763 const struct wcn36xx_hal_msg_header
*msg_header
= buf
;
2764 struct ieee80211_hw
*hw
= priv
;
2765 struct wcn36xx
*wcn
= hw
->priv
;
2766 struct wcn36xx_hal_ind_msg
*msg_ind
;
2767 wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP
, "SMD <<< ", buf
, len
);
2769 switch (msg_header
->msg_type
) {
2770 case WCN36XX_HAL_START_RSP
:
2771 case WCN36XX_HAL_CONFIG_STA_RSP
:
2772 case WCN36XX_HAL_CONFIG_BSS_RSP
:
2773 case WCN36XX_HAL_ADD_STA_SELF_RSP
:
2774 case WCN36XX_HAL_STOP_RSP
:
2775 case WCN36XX_HAL_DEL_STA_SELF_RSP
:
2776 case WCN36XX_HAL_DELETE_STA_RSP
:
2777 case WCN36XX_HAL_INIT_SCAN_RSP
:
2778 case WCN36XX_HAL_START_SCAN_RSP
:
2779 case WCN36XX_HAL_END_SCAN_RSP
:
2780 case WCN36XX_HAL_FINISH_SCAN_RSP
:
2781 case WCN36XX_HAL_DOWNLOAD_NV_RSP
:
2782 case WCN36XX_HAL_DELETE_BSS_RSP
:
2783 case WCN36XX_HAL_SEND_BEACON_RSP
:
2784 case WCN36XX_HAL_SET_LINK_ST_RSP
:
2785 case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP
:
2786 case WCN36XX_HAL_SET_BSSKEY_RSP
:
2787 case WCN36XX_HAL_SET_STAKEY_RSP
:
2788 case WCN36XX_HAL_RMV_STAKEY_RSP
:
2789 case WCN36XX_HAL_RMV_BSSKEY_RSP
:
2790 case WCN36XX_HAL_ENTER_BMPS_RSP
:
2791 case WCN36XX_HAL_SET_POWER_PARAMS_RSP
:
2792 case WCN36XX_HAL_EXIT_BMPS_RSP
:
2793 case WCN36XX_HAL_KEEP_ALIVE_RSP
:
2794 case WCN36XX_HAL_DUMP_COMMAND_RSP
:
2795 case WCN36XX_HAL_ADD_BA_SESSION_RSP
:
2796 case WCN36XX_HAL_ADD_BA_RSP
:
2797 case WCN36XX_HAL_DEL_BA_RSP
:
2798 case WCN36XX_HAL_TRIGGER_BA_RSP
:
2799 case WCN36XX_HAL_UPDATE_CFG_RSP
:
2800 case WCN36XX_HAL_JOIN_RSP
:
2801 case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP
:
2802 case WCN36XX_HAL_CH_SWITCH_RSP
:
2803 case WCN36XX_HAL_PROCESS_PTT_RSP
:
2804 case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP
:
2805 case WCN36XX_HAL_8023_MULTICAST_LIST_RSP
:
2806 case WCN36XX_HAL_START_SCAN_OFFLOAD_RSP
:
2807 case WCN36XX_HAL_STOP_SCAN_OFFLOAD_RSP
:
2808 memcpy(wcn
->hal_buf
, buf
, len
);
2809 wcn
->hal_rsp_len
= len
;
2810 complete(&wcn
->hal_rsp_compl
);
2813 case WCN36XX_HAL_COEX_IND
:
2814 case WCN36XX_HAL_AVOID_FREQ_RANGE_IND
:
2815 case WCN36XX_HAL_DEL_BA_IND
:
2816 case WCN36XX_HAL_OTA_TX_COMPL_IND
:
2817 case WCN36XX_HAL_MISSED_BEACON_IND
:
2818 case WCN36XX_HAL_DELETE_STA_CONTEXT_IND
:
2819 case WCN36XX_HAL_PRINT_REG_INFO_IND
:
2820 case WCN36XX_HAL_SCAN_OFFLOAD_IND
:
2821 msg_ind
= kmalloc(sizeof(*msg_ind
) + len
, GFP_ATOMIC
);
2823 wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
2824 msg_header
->msg_type
);
2828 msg_ind
->msg_len
= len
;
2829 memcpy(msg_ind
->msg
, buf
, len
);
2831 spin_lock(&wcn
->hal_ind_lock
);
2832 list_add_tail(&msg_ind
->list
, &wcn
->hal_ind_queue
);
2833 queue_work(wcn
->hal_ind_wq
, &wcn
->hal_ind_work
);
2834 spin_unlock(&wcn
->hal_ind_lock
);
2835 wcn36xx_dbg(WCN36XX_DBG_HAL
, "indication arrived\n");
2838 wcn36xx_err("SMD_EVENT (%d) not supported\n",
2839 msg_header
->msg_type
);
2845 static void wcn36xx_ind_smd_work(struct work_struct
*work
)
2847 struct wcn36xx
*wcn
=
2848 container_of(work
, struct wcn36xx
, hal_ind_work
);
2851 struct wcn36xx_hal_msg_header
*msg_header
;
2852 struct wcn36xx_hal_ind_msg
*hal_ind_msg
;
2853 unsigned long flags
;
2855 spin_lock_irqsave(&wcn
->hal_ind_lock
, flags
);
2857 if (list_empty(&wcn
->hal_ind_queue
)) {
2858 spin_unlock_irqrestore(&wcn
->hal_ind_lock
, flags
);
2862 hal_ind_msg
= list_first_entry(&wcn
->hal_ind_queue
,
2863 struct wcn36xx_hal_ind_msg
,
2865 list_del(&hal_ind_msg
->list
);
2866 spin_unlock_irqrestore(&wcn
->hal_ind_lock
, flags
);
2868 msg_header
= (struct wcn36xx_hal_msg_header
*)hal_ind_msg
->msg
;
2870 switch (msg_header
->msg_type
) {
2871 case WCN36XX_HAL_COEX_IND
:
2872 case WCN36XX_HAL_DEL_BA_IND
:
2873 case WCN36XX_HAL_AVOID_FREQ_RANGE_IND
:
2875 case WCN36XX_HAL_OTA_TX_COMPL_IND
:
2876 wcn36xx_smd_tx_compl_ind(wcn
,
2878 hal_ind_msg
->msg_len
);
2880 case WCN36XX_HAL_MISSED_BEACON_IND
:
2881 wcn36xx_smd_missed_beacon_ind(wcn
,
2883 hal_ind_msg
->msg_len
);
2885 case WCN36XX_HAL_DELETE_STA_CONTEXT_IND
:
2886 wcn36xx_smd_delete_sta_context_ind(wcn
,
2888 hal_ind_msg
->msg_len
);
2890 case WCN36XX_HAL_PRINT_REG_INFO_IND
:
2891 wcn36xx_smd_print_reg_info_ind(wcn
,
2893 hal_ind_msg
->msg_len
);
2895 case WCN36XX_HAL_SCAN_OFFLOAD_IND
:
2896 wcn36xx_smd_hw_scan_ind(wcn
, hal_ind_msg
->msg
,
2897 hal_ind_msg
->msg_len
);
2900 wcn36xx_err("SMD_EVENT (%d) not supported\n",
2901 msg_header
->msg_type
);
2908 int wcn36xx_smd_open(struct wcn36xx
*wcn
)
2910 wcn
->hal_ind_wq
= create_freezable_workqueue("wcn36xx_smd_ind");
2911 if (!wcn
->hal_ind_wq
)
2914 INIT_WORK(&wcn
->hal_ind_work
, wcn36xx_ind_smd_work
);
2915 INIT_LIST_HEAD(&wcn
->hal_ind_queue
);
2916 spin_lock_init(&wcn
->hal_ind_lock
);
2921 void wcn36xx_smd_close(struct wcn36xx
*wcn
)
2923 struct wcn36xx_hal_ind_msg
*msg
, *tmp
;
2925 cancel_work_sync(&wcn
->hal_ind_work
);
2926 destroy_workqueue(wcn
->hal_ind_wq
);
2928 list_for_each_entry_safe(msg
, tmp
, &wcn
->hal_ind_queue
, list
)