1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright(c) 2009-2012 Realtek Corporation.*/ |
3 | |
4 | #include "wifi.h" |
5 | #include "rc.h" |
6 | #include "base.h" |
7 | #include "efuse.h" |
8 | #include "cam.h" |
9 | #include "ps.h" |
10 | #include "regd.h" |
11 | #include "pci.h" |
12 | #include <linux/ip.h> |
13 | #include <linux/module.h> |
14 | #include <linux/udp.h> |
15 | |
16 | /* |
17 | *NOTICE!!!: This file will be very big, we should |
18 | *keep it clear under following roles: |
19 | * |
20 | *This file include following parts, so, if you add new |
21 | *functions into this file, please check which part it |
22 | *should includes. or check if you should add new part |
23 | *for this file: |
24 | * |
25 | *1) mac80211 init functions |
26 | *2) tx information functions |
27 | *3) functions called by core.c |
28 | *4) wq & timer callback functions |
29 | *5) frame process functions |
30 | *6) IOT functions |
31 | *7) sysfs functions |
32 | *8) vif functions |
33 | *9) ... |
34 | */ |
35 | |
36 | /********************************************************* |
37 | * |
38 | * mac80211 init functions |
39 | * |
40 | *********************************************************/ |
41 | static struct ieee80211_channel rtl_channeltable_2g[] = { |
42 | {.center_freq = 2412, .hw_value = 1,}, |
43 | {.center_freq = 2417, .hw_value = 2,}, |
44 | {.center_freq = 2422, .hw_value = 3,}, |
45 | {.center_freq = 2427, .hw_value = 4,}, |
46 | {.center_freq = 2432, .hw_value = 5,}, |
47 | {.center_freq = 2437, .hw_value = 6,}, |
48 | {.center_freq = 2442, .hw_value = 7,}, |
49 | {.center_freq = 2447, .hw_value = 8,}, |
50 | {.center_freq = 2452, .hw_value = 9,}, |
51 | {.center_freq = 2457, .hw_value = 10,}, |
52 | {.center_freq = 2462, .hw_value = 11,}, |
53 | {.center_freq = 2467, .hw_value = 12,}, |
54 | {.center_freq = 2472, .hw_value = 13,}, |
55 | {.center_freq = 2484, .hw_value = 14,}, |
56 | }; |
57 | |
58 | static struct ieee80211_channel rtl_channeltable_5g[] = { |
59 | {.center_freq = 5180, .hw_value = 36,}, |
60 | {.center_freq = 5200, .hw_value = 40,}, |
61 | {.center_freq = 5220, .hw_value = 44,}, |
62 | {.center_freq = 5240, .hw_value = 48,}, |
63 | {.center_freq = 5260, .hw_value = 52,}, |
64 | {.center_freq = 5280, .hw_value = 56,}, |
65 | {.center_freq = 5300, .hw_value = 60,}, |
66 | {.center_freq = 5320, .hw_value = 64,}, |
67 | {.center_freq = 5500, .hw_value = 100,}, |
68 | {.center_freq = 5520, .hw_value = 104,}, |
69 | {.center_freq = 5540, .hw_value = 108,}, |
70 | {.center_freq = 5560, .hw_value = 112,}, |
71 | {.center_freq = 5580, .hw_value = 116,}, |
72 | {.center_freq = 5600, .hw_value = 120,}, |
73 | {.center_freq = 5620, .hw_value = 124,}, |
74 | {.center_freq = 5640, .hw_value = 128,}, |
75 | {.center_freq = 5660, .hw_value = 132,}, |
76 | {.center_freq = 5680, .hw_value = 136,}, |
77 | {.center_freq = 5700, .hw_value = 140,}, |
78 | {.center_freq = 5745, .hw_value = 149,}, |
79 | {.center_freq = 5765, .hw_value = 153,}, |
80 | {.center_freq = 5785, .hw_value = 157,}, |
81 | {.center_freq = 5805, .hw_value = 161,}, |
82 | {.center_freq = 5825, .hw_value = 165,}, |
83 | }; |
84 | |
85 | static struct ieee80211_rate rtl_ratetable_2g[] = { |
86 | {.bitrate = 10, .hw_value = 0x00,}, |
87 | {.bitrate = 20, .hw_value = 0x01,}, |
88 | {.bitrate = 55, .hw_value = 0x02,}, |
89 | {.bitrate = 110, .hw_value = 0x03,}, |
90 | {.bitrate = 60, .hw_value = 0x04,}, |
91 | {.bitrate = 90, .hw_value = 0x05,}, |
92 | {.bitrate = 120, .hw_value = 0x06,}, |
93 | {.bitrate = 180, .hw_value = 0x07,}, |
94 | {.bitrate = 240, .hw_value = 0x08,}, |
95 | {.bitrate = 360, .hw_value = 0x09,}, |
96 | {.bitrate = 480, .hw_value = 0x0a,}, |
97 | {.bitrate = 540, .hw_value = 0x0b,}, |
98 | }; |
99 | |
100 | static struct ieee80211_rate rtl_ratetable_5g[] = { |
101 | {.bitrate = 60, .hw_value = 0x04,}, |
102 | {.bitrate = 90, .hw_value = 0x05,}, |
103 | {.bitrate = 120, .hw_value = 0x06,}, |
104 | {.bitrate = 180, .hw_value = 0x07,}, |
105 | {.bitrate = 240, .hw_value = 0x08,}, |
106 | {.bitrate = 360, .hw_value = 0x09,}, |
107 | {.bitrate = 480, .hw_value = 0x0a,}, |
108 | {.bitrate = 540, .hw_value = 0x0b,}, |
109 | }; |
110 | |
111 | static const struct ieee80211_supported_band rtl_band_2ghz = { |
112 | .band = NL80211_BAND_2GHZ, |
113 | |
114 | .channels = rtl_channeltable_2g, |
115 | .n_channels = ARRAY_SIZE(rtl_channeltable_2g), |
116 | |
117 | .bitrates = rtl_ratetable_2g, |
118 | .n_bitrates = ARRAY_SIZE(rtl_ratetable_2g), |
119 | |
120 | .ht_cap = {0}, |
121 | }; |
122 | |
123 | static struct ieee80211_supported_band rtl_band_5ghz = { |
124 | .band = NL80211_BAND_5GHZ, |
125 | |
126 | .channels = rtl_channeltable_5g, |
127 | .n_channels = ARRAY_SIZE(rtl_channeltable_5g), |
128 | |
129 | .bitrates = rtl_ratetable_5g, |
130 | .n_bitrates = ARRAY_SIZE(rtl_ratetable_5g), |
131 | |
132 | .ht_cap = {0}, |
133 | }; |
134 | |
135 | static const u8 tid_to_ac[] = { |
136 | 2, /* IEEE80211_AC_BE */ |
137 | 3, /* IEEE80211_AC_BK */ |
138 | 3, /* IEEE80211_AC_BK */ |
139 | 2, /* IEEE80211_AC_BE */ |
140 | 1, /* IEEE80211_AC_VI */ |
141 | 1, /* IEEE80211_AC_VI */ |
142 | 0, /* IEEE80211_AC_VO */ |
143 | 0, /* IEEE80211_AC_VO */ |
144 | }; |
145 | |
146 | u8 rtl_tid_to_ac(u8 tid) |
147 | { |
148 | return tid_to_ac[tid]; |
149 | } |
150 | EXPORT_SYMBOL_GPL(rtl_tid_to_ac); |
151 | |
152 | static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, |
153 | struct ieee80211_sta_ht_cap *ht_cap) |
154 | { |
155 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
156 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
157 | |
158 | ht_cap->ht_supported = true; |
159 | ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | |
160 | IEEE80211_HT_CAP_SGI_40 | |
161 | IEEE80211_HT_CAP_SGI_20 | |
162 | IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU; |
163 | |
164 | if (rtlpriv->rtlhal.disable_amsdu_8k) |
165 | ht_cap->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; |
166 | |
167 | /* |
168 | *Maximum length of AMPDU that the STA can receive. |
169 | *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) |
170 | */ |
171 | ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; |
172 | |
173 | /*Minimum MPDU start spacing , */ |
174 | ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; |
175 | |
176 | ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |
177 | |
178 | /*hw->wiphy->bands[NL80211_BAND_2GHZ] |
179 | *base on ant_num |
180 | *rx_mask: RX mask |
181 | *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7 |
182 | *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15 |
183 | *if rx_ant >= 3 rx_mask[2]= 0xff; |
184 | *if BW_40 rx_mask[4]= 0x01; |
185 | *highest supported RX rate |
186 | */ |
187 | if (rtlpriv->dm.supp_phymode_switch) { |
188 | pr_info("Support phy mode switch\n" ); |
189 | |
190 | ht_cap->mcs.rx_mask[0] = 0xFF; |
191 | ht_cap->mcs.rx_mask[1] = 0xFF; |
192 | ht_cap->mcs.rx_mask[4] = 0x01; |
193 | |
194 | ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); |
195 | } else { |
196 | if (get_rf_type(rtlphy) == RF_1T2R || |
197 | get_rf_type(rtlphy) == RF_2T2R) { |
198 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, |
199 | "1T2R or 2T2R\n" ); |
200 | ht_cap->mcs.rx_mask[0] = 0xFF; |
201 | ht_cap->mcs.rx_mask[1] = 0xFF; |
202 | ht_cap->mcs.rx_mask[4] = 0x01; |
203 | |
204 | ht_cap->mcs.rx_highest = |
205 | cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); |
206 | } else if (get_rf_type(rtlphy) == RF_1T1R) { |
207 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n" ); |
208 | |
209 | ht_cap->mcs.rx_mask[0] = 0xFF; |
210 | ht_cap->mcs.rx_mask[1] = 0x00; |
211 | ht_cap->mcs.rx_mask[4] = 0x01; |
212 | |
213 | ht_cap->mcs.rx_highest = |
214 | cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7); |
215 | } |
216 | } |
217 | } |
218 | |
219 | static void _rtl_init_hw_vht_capab(struct ieee80211_hw *hw, |
220 | struct ieee80211_sta_vht_cap *vht_cap) |
221 | { |
222 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
223 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
224 | |
225 | if (!(rtlpriv->cfg->spec_ver & RTL_SPEC_SUPPORT_VHT)) |
226 | return; |
227 | |
228 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE || |
229 | rtlhal->hw_type == HARDWARE_TYPE_RTL8822BE) { |
230 | u16 mcs_map; |
231 | |
232 | vht_cap->vht_supported = true; |
233 | vht_cap->cap = |
234 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | |
235 | IEEE80211_VHT_CAP_SHORT_GI_80 | |
236 | IEEE80211_VHT_CAP_TXSTBC | |
237 | IEEE80211_VHT_CAP_RXSTBC_1 | |
238 | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | |
239 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | |
240 | IEEE80211_VHT_CAP_HTC_VHT | |
241 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | |
242 | IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | |
243 | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | |
244 | 0; |
245 | |
246 | mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | |
247 | IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 | |
248 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | |
249 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | |
250 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | |
251 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | |
252 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | |
253 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; |
254 | |
255 | vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); |
256 | vht_cap->vht_mcs.rx_highest = |
257 | cpu_to_le16(MAX_BIT_RATE_SHORT_GI_2NSS_80MHZ_MCS9); |
258 | vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); |
259 | vht_cap->vht_mcs.tx_highest = |
260 | cpu_to_le16(MAX_BIT_RATE_SHORT_GI_2NSS_80MHZ_MCS9); |
261 | } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { |
262 | u16 mcs_map; |
263 | |
264 | vht_cap->vht_supported = true; |
265 | vht_cap->cap = |
266 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | |
267 | IEEE80211_VHT_CAP_SHORT_GI_80 | |
268 | IEEE80211_VHT_CAP_TXSTBC | |
269 | IEEE80211_VHT_CAP_RXSTBC_1 | |
270 | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | |
271 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | |
272 | IEEE80211_VHT_CAP_HTC_VHT | |
273 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | |
274 | IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | |
275 | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | |
276 | 0; |
277 | |
278 | mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | |
279 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 | |
280 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | |
281 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | |
282 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | |
283 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | |
284 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | |
285 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; |
286 | |
287 | vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); |
288 | vht_cap->vht_mcs.rx_highest = |
289 | cpu_to_le16(MAX_BIT_RATE_SHORT_GI_1NSS_80MHZ_MCS9); |
290 | vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); |
291 | vht_cap->vht_mcs.tx_highest = |
292 | cpu_to_le16(MAX_BIT_RATE_SHORT_GI_1NSS_80MHZ_MCS9); |
293 | } |
294 | } |
295 | |
296 | static void _rtl_init_mac80211(struct ieee80211_hw *hw) |
297 | { |
298 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
299 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
300 | struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); |
301 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
302 | struct ieee80211_supported_band *sband; |
303 | |
304 | if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && |
305 | rtlhal->bandset == BAND_ON_BOTH) { |
306 | /* 1: 2.4 G bands */ |
307 | /* <1> use mac->bands as mem for hw->wiphy->bands */ |
308 | sband = &(rtlmac->bands[NL80211_BAND_2GHZ]); |
309 | |
310 | /* <2> set hw->wiphy->bands[NL80211_BAND_2GHZ] |
311 | * to default value(1T1R) */ |
312 | memcpy(&(rtlmac->bands[NL80211_BAND_2GHZ]), &rtl_band_2ghz, |
313 | sizeof(struct ieee80211_supported_band)); |
314 | |
315 | /* <3> init ht cap base on ant_num */ |
316 | _rtl_init_hw_ht_capab(hw, ht_cap: &sband->ht_cap); |
317 | |
318 | /* <4> set mac->sband to wiphy->sband */ |
319 | hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; |
320 | |
321 | /* 2: 5 G bands */ |
322 | /* <1> use mac->bands as mem for hw->wiphy->bands */ |
323 | sband = &(rtlmac->bands[NL80211_BAND_5GHZ]); |
324 | |
325 | /* <2> set hw->wiphy->bands[NL80211_BAND_5GHZ] |
326 | * to default value(1T1R) */ |
327 | memcpy(&(rtlmac->bands[NL80211_BAND_5GHZ]), &rtl_band_5ghz, |
328 | sizeof(struct ieee80211_supported_band)); |
329 | |
330 | /* <3> init ht cap base on ant_num */ |
331 | _rtl_init_hw_ht_capab(hw, ht_cap: &sband->ht_cap); |
332 | |
333 | _rtl_init_hw_vht_capab(hw, vht_cap: &sband->vht_cap); |
334 | /* <4> set mac->sband to wiphy->sband */ |
335 | hw->wiphy->bands[NL80211_BAND_5GHZ] = sband; |
336 | } else { |
337 | if (rtlhal->current_bandtype == BAND_ON_2_4G) { |
338 | /* <1> use mac->bands as mem for hw->wiphy->bands */ |
339 | sband = &(rtlmac->bands[NL80211_BAND_2GHZ]); |
340 | |
341 | /* <2> set hw->wiphy->bands[NL80211_BAND_2GHZ] |
342 | * to default value(1T1R) */ |
343 | memcpy(&(rtlmac->bands[NL80211_BAND_2GHZ]), |
344 | &rtl_band_2ghz, |
345 | sizeof(struct ieee80211_supported_band)); |
346 | |
347 | /* <3> init ht cap base on ant_num */ |
348 | _rtl_init_hw_ht_capab(hw, ht_cap: &sband->ht_cap); |
349 | |
350 | /* <4> set mac->sband to wiphy->sband */ |
351 | hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; |
352 | } else if (rtlhal->current_bandtype == BAND_ON_5G) { |
353 | /* <1> use mac->bands as mem for hw->wiphy->bands */ |
354 | sband = &(rtlmac->bands[NL80211_BAND_5GHZ]); |
355 | |
356 | /* <2> set hw->wiphy->bands[NL80211_BAND_5GHZ] |
357 | * to default value(1T1R) */ |
358 | memcpy(&(rtlmac->bands[NL80211_BAND_5GHZ]), |
359 | &rtl_band_5ghz, |
360 | sizeof(struct ieee80211_supported_band)); |
361 | |
362 | /* <3> init ht cap base on ant_num */ |
363 | _rtl_init_hw_ht_capab(hw, ht_cap: &sband->ht_cap); |
364 | |
365 | _rtl_init_hw_vht_capab(hw, vht_cap: &sband->vht_cap); |
366 | /* <4> set mac->sband to wiphy->sband */ |
367 | hw->wiphy->bands[NL80211_BAND_5GHZ] = sband; |
368 | } else { |
369 | pr_err("Err BAND %d\n" , |
370 | rtlhal->current_bandtype); |
371 | } |
372 | } |
373 | /* <5> set hw caps */ |
374 | ieee80211_hw_set(hw, SIGNAL_DBM); |
375 | ieee80211_hw_set(hw, RX_INCLUDES_FCS); |
376 | ieee80211_hw_set(hw, AMPDU_AGGREGATION); |
377 | ieee80211_hw_set(hw, MFP_CAPABLE); |
378 | ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); |
379 | ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); |
380 | ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); |
381 | |
382 | /* swlps or hwlps has been set in diff chip in init_sw_vars */ |
383 | if (rtlpriv->psc.swctrl_lps) { |
384 | ieee80211_hw_set(hw, SUPPORTS_PS); |
385 | ieee80211_hw_set(hw, PS_NULLFUNC_STACK); |
386 | } |
387 | if (rtlpriv->psc.fwctrl_lps) { |
388 | ieee80211_hw_set(hw, SUPPORTS_PS); |
389 | ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); |
390 | } |
391 | hw->wiphy->interface_modes = |
392 | BIT(NL80211_IFTYPE_AP) | |
393 | BIT(NL80211_IFTYPE_STATION) | |
394 | BIT(NL80211_IFTYPE_ADHOC) | |
395 | BIT(NL80211_IFTYPE_MESH_POINT) | |
396 | BIT(NL80211_IFTYPE_P2P_CLIENT) | |
397 | BIT(NL80211_IFTYPE_P2P_GO); |
398 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
399 | |
400 | hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; |
401 | |
402 | hw->wiphy->rts_threshold = 2347; |
403 | |
404 | hw->queues = AC_MAX; |
405 | hw->extra_tx_headroom = RTL_TX_HEADER_SIZE; |
406 | |
407 | /* TODO: Correct this value for our hw */ |
408 | hw->max_listen_interval = MAX_LISTEN_INTERVAL; |
409 | hw->max_rate_tries = MAX_RATE_TRIES; |
410 | /* hw->max_rates = 1; */ |
411 | hw->sta_data_size = sizeof(struct rtl_sta_info); |
412 | |
413 | /* wowlan is not supported by kernel if CONFIG_PM is not defined */ |
414 | #ifdef CONFIG_PM |
415 | if (rtlpriv->psc.wo_wlan_mode) { |
416 | if (rtlpriv->psc.wo_wlan_mode & WAKE_ON_MAGIC_PACKET) |
417 | rtlpriv->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT; |
418 | if (rtlpriv->psc.wo_wlan_mode & WAKE_ON_PATTERN_MATCH) { |
419 | rtlpriv->wowlan.n_patterns = |
420 | MAX_SUPPORT_WOL_PATTERN_NUM; |
421 | rtlpriv->wowlan.pattern_min_len = MIN_WOL_PATTERN_SIZE; |
422 | rtlpriv->wowlan.pattern_max_len = MAX_WOL_PATTERN_SIZE; |
423 | } |
424 | hw->wiphy->wowlan = &rtlpriv->wowlan; |
425 | } |
426 | #endif |
427 | |
428 | /* <6> mac address */ |
429 | if (is_valid_ether_addr(addr: rtlefuse->dev_addr)) { |
430 | SET_IEEE80211_PERM_ADDR(hw, addr: rtlefuse->dev_addr); |
431 | } else { |
432 | u8 rtlmac1[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 }; |
433 | |
434 | get_random_bytes(buf: (rtlmac1 + (ETH_ALEN - 1)), len: 1); |
435 | SET_IEEE80211_PERM_ADDR(hw, addr: rtlmac1); |
436 | } |
437 | } |
438 | |
439 | static void rtl_watchdog_wq_callback(struct work_struct *work); |
440 | static void rtl_fwevt_wq_callback(struct work_struct *work); |
441 | static void rtl_c2hcmd_wq_callback(struct work_struct *work); |
442 | |
443 | static int _rtl_init_deferred_work(struct ieee80211_hw *hw) |
444 | { |
445 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
446 | struct workqueue_struct *wq; |
447 | |
448 | wq = alloc_workqueue(fmt: "%s" , flags: 0, max_active: 0, rtlpriv->cfg->name); |
449 | if (!wq) |
450 | return -ENOMEM; |
451 | |
452 | /* <1> timer */ |
453 | timer_setup(&rtlpriv->works.watchdog_timer, |
454 | rtl_watch_dog_timer_callback, 0); |
455 | |
456 | /* <2> work queue */ |
457 | rtlpriv->works.hw = hw; |
458 | rtlpriv->works.rtl_wq = wq; |
459 | |
460 | INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq, |
461 | rtl_watchdog_wq_callback); |
462 | INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, |
463 | rtl_ips_nic_off_wq_callback); |
464 | INIT_DELAYED_WORK(&rtlpriv->works.ps_work, rtl_swlps_wq_callback); |
465 | INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq, |
466 | rtl_swlps_rfon_wq_callback); |
467 | INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq, rtl_fwevt_wq_callback); |
468 | INIT_DELAYED_WORK(&rtlpriv->works.c2hcmd_wq, rtl_c2hcmd_wq_callback); |
469 | return 0; |
470 | } |
471 | |
472 | void rtl_deinit_deferred_work(struct ieee80211_hw *hw, bool ips_wq) |
473 | { |
474 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
475 | |
476 | del_timer_sync(timer: &rtlpriv->works.watchdog_timer); |
477 | |
478 | cancel_delayed_work_sync(dwork: &rtlpriv->works.watchdog_wq); |
479 | if (ips_wq) |
480 | cancel_delayed_work(dwork: &rtlpriv->works.ips_nic_off_wq); |
481 | else |
482 | cancel_delayed_work_sync(dwork: &rtlpriv->works.ips_nic_off_wq); |
483 | cancel_delayed_work_sync(dwork: &rtlpriv->works.ps_work); |
484 | cancel_delayed_work_sync(dwork: &rtlpriv->works.ps_rfon_wq); |
485 | cancel_delayed_work_sync(dwork: &rtlpriv->works.fwevt_wq); |
486 | cancel_delayed_work_sync(dwork: &rtlpriv->works.c2hcmd_wq); |
487 | } |
488 | EXPORT_SYMBOL_GPL(rtl_deinit_deferred_work); |
489 | |
490 | void rtl_init_rfkill(struct ieee80211_hw *hw) |
491 | { |
492 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
493 | |
494 | bool radio_state; |
495 | bool blocked; |
496 | u8 valid = 0; |
497 | |
498 | /*set init state to on */ |
499 | rtlpriv->rfkill.rfkill_state = true; |
500 | wiphy_rfkill_set_hw_state(wiphy: hw->wiphy, blocked: 0); |
501 | |
502 | radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); |
503 | |
504 | if (valid) { |
505 | pr_info("rtlwifi: wireless switch is %s\n" , |
506 | rtlpriv->rfkill.rfkill_state ? "on" : "off" ); |
507 | |
508 | rtlpriv->rfkill.rfkill_state = radio_state; |
509 | |
510 | blocked = rtlpriv->rfkill.rfkill_state != 1; |
511 | wiphy_rfkill_set_hw_state(wiphy: hw->wiphy, blocked); |
512 | } |
513 | |
514 | wiphy_rfkill_start_polling(wiphy: hw->wiphy); |
515 | } |
516 | EXPORT_SYMBOL(rtl_init_rfkill); |
517 | |
518 | void rtl_deinit_rfkill(struct ieee80211_hw *hw) |
519 | { |
520 | wiphy_rfkill_stop_polling(wiphy: hw->wiphy); |
521 | } |
522 | EXPORT_SYMBOL_GPL(rtl_deinit_rfkill); |
523 | |
524 | int rtl_init_core(struct ieee80211_hw *hw) |
525 | { |
526 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
527 | struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); |
528 | |
529 | /* <1> init mac80211 */ |
530 | _rtl_init_mac80211(hw); |
531 | rtlmac->hw = hw; |
532 | |
533 | /* <2> rate control register */ |
534 | hw->rate_control_algorithm = "rtl_rc" ; |
535 | |
536 | /* |
537 | * <3> init CRDA must come after init |
538 | * mac80211 hw in _rtl_init_mac80211. |
539 | */ |
540 | if (rtl_regd_init(hw, reg_notifier: rtl_reg_notifier)) { |
541 | pr_err("REGD init failed\n" ); |
542 | return 1; |
543 | } |
544 | |
545 | /* <4> locks */ |
546 | mutex_init(&rtlpriv->locks.conf_mutex); |
547 | mutex_init(&rtlpriv->locks.ips_mutex); |
548 | mutex_init(&rtlpriv->locks.lps_mutex); |
549 | spin_lock_init(&rtlpriv->locks.irq_th_lock); |
550 | spin_lock_init(&rtlpriv->locks.h2c_lock); |
551 | spin_lock_init(&rtlpriv->locks.rf_ps_lock); |
552 | spin_lock_init(&rtlpriv->locks.rf_lock); |
553 | spin_lock_init(&rtlpriv->locks.waitq_lock); |
554 | spin_lock_init(&rtlpriv->locks.entry_list_lock); |
555 | spin_lock_init(&rtlpriv->locks.scan_list_lock); |
556 | spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); |
557 | spin_lock_init(&rtlpriv->locks.fw_ps_lock); |
558 | spin_lock_init(&rtlpriv->locks.iqk_lock); |
559 | /* <5> init list */ |
560 | INIT_LIST_HEAD(list: &rtlpriv->entry_list); |
561 | INIT_LIST_HEAD(list: &rtlpriv->scan_list.list); |
562 | skb_queue_head_init(list: &rtlpriv->tx_report.queue); |
563 | skb_queue_head_init(list: &rtlpriv->c2hcmd_queue); |
564 | |
565 | rtlmac->link_state = MAC80211_NOLINK; |
566 | |
567 | /* <6> init deferred work */ |
568 | return _rtl_init_deferred_work(hw); |
569 | } |
570 | EXPORT_SYMBOL_GPL(rtl_init_core); |
571 | |
572 | static void rtl_free_entries_from_scan_list(struct ieee80211_hw *hw); |
573 | static void rtl_free_entries_from_ack_queue(struct ieee80211_hw *hw, |
574 | bool timeout); |
575 | |
576 | void rtl_deinit_core(struct ieee80211_hw *hw) |
577 | { |
578 | rtl_c2hcmd_launcher(hw, exec: 0); |
579 | rtl_free_entries_from_scan_list(hw); |
580 | rtl_free_entries_from_ack_queue(hw, timeout: false); |
581 | } |
582 | EXPORT_SYMBOL_GPL(rtl_deinit_core); |
583 | |
584 | void rtl_init_rx_config(struct ieee80211_hw *hw) |
585 | { |
586 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
587 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
588 | |
589 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); |
590 | } |
591 | EXPORT_SYMBOL_GPL(rtl_init_rx_config); |
592 | |
593 | /********************************************************* |
594 | * |
595 | * tx information functions |
596 | * |
597 | *********************************************************/ |
598 | static void _rtl_qurey_shortpreamble_mode(struct ieee80211_hw *hw, |
599 | struct rtl_tcb_desc *tcb_desc, |
600 | struct ieee80211_tx_info *info) |
601 | { |
602 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
603 | u8 rate_flag = info->control.rates[0].flags; |
604 | |
605 | tcb_desc->use_shortpreamble = false; |
606 | |
607 | /* 1M can only use Long Preamble. 11B spec */ |
608 | if (tcb_desc->hw_rate == rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]) |
609 | return; |
610 | else if (rate_flag & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) |
611 | tcb_desc->use_shortpreamble = true; |
612 | |
613 | return; |
614 | } |
615 | |
616 | static void _rtl_query_shortgi(struct ieee80211_hw *hw, |
617 | struct ieee80211_sta *sta, |
618 | struct rtl_tcb_desc *tcb_desc, |
619 | struct ieee80211_tx_info *info) |
620 | { |
621 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
622 | u8 rate_flag = info->control.rates[0].flags; |
623 | u8 sgi_40 = 0, sgi_20 = 0, bw_40 = 0; |
624 | u8 sgi_80 = 0, bw_80 = 0; |
625 | |
626 | tcb_desc->use_shortgi = false; |
627 | |
628 | if (sta == NULL) |
629 | return; |
630 | |
631 | sgi_40 = sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40; |
632 | sgi_20 = sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20; |
633 | sgi_80 = sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80; |
634 | |
635 | if (!sta->deflink.ht_cap.ht_supported && |
636 | !sta->deflink.vht_cap.vht_supported) |
637 | return; |
638 | |
639 | if (!sgi_40 && !sgi_20) |
640 | return; |
641 | |
642 | if (mac->opmode == NL80211_IFTYPE_STATION) { |
643 | bw_40 = mac->bw_40; |
644 | bw_80 = mac->bw_80; |
645 | } else if (mac->opmode == NL80211_IFTYPE_AP || |
646 | mac->opmode == NL80211_IFTYPE_ADHOC || |
647 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { |
648 | bw_40 = sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
649 | bw_80 = sta->deflink.vht_cap.vht_supported; |
650 | } |
651 | |
652 | if (bw_80) { |
653 | if (sgi_80) |
654 | tcb_desc->use_shortgi = true; |
655 | else |
656 | tcb_desc->use_shortgi = false; |
657 | } else { |
658 | if (bw_40 && sgi_40) |
659 | tcb_desc->use_shortgi = true; |
660 | else if (!bw_40 && sgi_20) |
661 | tcb_desc->use_shortgi = true; |
662 | } |
663 | |
664 | if (!(rate_flag & IEEE80211_TX_RC_SHORT_GI)) |
665 | tcb_desc->use_shortgi = false; |
666 | } |
667 | |
668 | static void _rtl_query_protection_mode(struct ieee80211_hw *hw, |
669 | struct rtl_tcb_desc *tcb_desc, |
670 | struct ieee80211_tx_info *info) |
671 | { |
672 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
673 | u8 rate_flag = info->control.rates[0].flags; |
674 | |
675 | /* Common Settings */ |
676 | tcb_desc->rts_stbc = false; |
677 | tcb_desc->cts_enable = false; |
678 | tcb_desc->rts_sc = 0; |
679 | tcb_desc->rts_bw = false; |
680 | tcb_desc->rts_use_shortpreamble = false; |
681 | tcb_desc->rts_use_shortgi = false; |
682 | |
683 | if (rate_flag & IEEE80211_TX_RC_USE_CTS_PROTECT) { |
684 | /* Use CTS-to-SELF in protection mode. */ |
685 | tcb_desc->rts_enable = true; |
686 | tcb_desc->cts_enable = true; |
687 | tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M]; |
688 | } else if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) { |
689 | /* Use RTS-CTS in protection mode. */ |
690 | tcb_desc->rts_enable = true; |
691 | tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M]; |
692 | } |
693 | } |
694 | |
695 | u8 rtl_mrate_idx_to_arfr_id(struct ieee80211_hw *hw, u8 rate_index, |
696 | enum wireless_mode wirelessmode) |
697 | { |
698 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
699 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
700 | u8 ret = 0; |
701 | |
702 | switch (rate_index) { |
703 | case RATR_INX_WIRELESS_NGB: |
704 | if (rtlphy->rf_type == RF_1T1R) |
705 | ret = RATEID_IDX_BGN_40M_1SS; |
706 | else |
707 | ret = RATEID_IDX_BGN_40M_2SS; |
708 | ; break; |
709 | case RATR_INX_WIRELESS_N: |
710 | case RATR_INX_WIRELESS_NG: |
711 | if (rtlphy->rf_type == RF_1T1R) |
712 | ret = RATEID_IDX_GN_N1SS; |
713 | else |
714 | ret = RATEID_IDX_GN_N2SS; |
715 | ; break; |
716 | case RATR_INX_WIRELESS_NB: |
717 | if (rtlphy->rf_type == RF_1T1R) |
718 | ret = RATEID_IDX_BGN_20M_1SS_BN; |
719 | else |
720 | ret = RATEID_IDX_BGN_20M_2SS_BN; |
721 | ; break; |
722 | case RATR_INX_WIRELESS_GB: |
723 | ret = RATEID_IDX_BG; |
724 | break; |
725 | case RATR_INX_WIRELESS_G: |
726 | ret = RATEID_IDX_G; |
727 | break; |
728 | case RATR_INX_WIRELESS_B: |
729 | ret = RATEID_IDX_B; |
730 | break; |
731 | case RATR_INX_WIRELESS_MC: |
732 | if (wirelessmode == WIRELESS_MODE_B || |
733 | wirelessmode == WIRELESS_MODE_G || |
734 | wirelessmode == WIRELESS_MODE_N_24G || |
735 | wirelessmode == WIRELESS_MODE_AC_24G) |
736 | ret = RATEID_IDX_BG; |
737 | else |
738 | ret = RATEID_IDX_G; |
739 | break; |
740 | case RATR_INX_WIRELESS_AC_5N: |
741 | if (rtlphy->rf_type == RF_1T1R) |
742 | ret = RATEID_IDX_VHT_1SS; |
743 | else |
744 | ret = RATEID_IDX_VHT_2SS; |
745 | break; |
746 | case RATR_INX_WIRELESS_AC_24N: |
747 | if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) { |
748 | if (rtlphy->rf_type == RF_1T1R) |
749 | ret = RATEID_IDX_VHT_1SS; |
750 | else |
751 | ret = RATEID_IDX_VHT_2SS; |
752 | } else { |
753 | if (rtlphy->rf_type == RF_1T1R) |
754 | ret = RATEID_IDX_MIX1; |
755 | else |
756 | ret = RATEID_IDX_MIX2; |
757 | } |
758 | break; |
759 | default: |
760 | ret = RATEID_IDX_BGN_40M_2SS; |
761 | break; |
762 | } |
763 | return ret; |
764 | } |
765 | EXPORT_SYMBOL(rtl_mrate_idx_to_arfr_id); |
766 | |
767 | static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, |
768 | struct ieee80211_sta *sta, |
769 | struct rtl_tcb_desc *tcb_desc) |
770 | { |
771 | #define SET_RATE_ID(rate_id) \ |
772 | ({typeof(rate_id) _id = rate_id; \ |
773 | ((rtlpriv->cfg->spec_ver & RTL_SPEC_NEW_RATEID) ? \ |
774 | rtl_mrate_idx_to_arfr_id(hw, _id, \ |
775 | (sta_entry ? sta_entry->wireless_mode : \ |
776 | WIRELESS_MODE_G)) : \ |
777 | _id); }) |
778 | |
779 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
780 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
781 | struct rtl_sta_info *sta_entry = NULL; |
782 | u8 ratr_index = SET_RATE_ID(RATR_INX_WIRELESS_MC); |
783 | |
784 | if (sta) { |
785 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; |
786 | ratr_index = sta_entry->ratr_index; |
787 | } |
788 | if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { |
789 | if (mac->opmode == NL80211_IFTYPE_STATION) { |
790 | tcb_desc->ratr_index = 0; |
791 | } else if (mac->opmode == NL80211_IFTYPE_ADHOC || |
792 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { |
793 | if (tcb_desc->multicast || tcb_desc->broadcast) { |
794 | tcb_desc->hw_rate = |
795 | rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; |
796 | tcb_desc->use_driver_rate = 1; |
797 | tcb_desc->ratr_index = |
798 | SET_RATE_ID(RATR_INX_WIRELESS_MC); |
799 | } else { |
800 | tcb_desc->ratr_index = ratr_index; |
801 | } |
802 | } else if (mac->opmode == NL80211_IFTYPE_AP) { |
803 | tcb_desc->ratr_index = ratr_index; |
804 | } |
805 | } |
806 | |
807 | if (rtlpriv->dm.useramask) { |
808 | tcb_desc->ratr_index = ratr_index; |
809 | /* TODO we will differentiate adhoc and station future */ |
810 | if (mac->opmode == NL80211_IFTYPE_STATION || |
811 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { |
812 | tcb_desc->mac_id = 0; |
813 | |
814 | if (sta && |
815 | (rtlpriv->cfg->spec_ver & RTL_SPEC_NEW_RATEID)) |
816 | ; /* use sta_entry->ratr_index */ |
817 | else if (mac->mode == WIRELESS_MODE_AC_5G) |
818 | tcb_desc->ratr_index = |
819 | SET_RATE_ID(RATR_INX_WIRELESS_AC_5N); |
820 | else if (mac->mode == WIRELESS_MODE_AC_24G) |
821 | tcb_desc->ratr_index = |
822 | SET_RATE_ID(RATR_INX_WIRELESS_AC_24N); |
823 | else if (mac->mode == WIRELESS_MODE_N_24G) |
824 | tcb_desc->ratr_index = |
825 | SET_RATE_ID(RATR_INX_WIRELESS_NGB); |
826 | else if (mac->mode == WIRELESS_MODE_N_5G) |
827 | tcb_desc->ratr_index = |
828 | SET_RATE_ID(RATR_INX_WIRELESS_NG); |
829 | else if (mac->mode & WIRELESS_MODE_G) |
830 | tcb_desc->ratr_index = |
831 | SET_RATE_ID(RATR_INX_WIRELESS_GB); |
832 | else if (mac->mode & WIRELESS_MODE_B) |
833 | tcb_desc->ratr_index = |
834 | SET_RATE_ID(RATR_INX_WIRELESS_B); |
835 | else if (mac->mode & WIRELESS_MODE_A) |
836 | tcb_desc->ratr_index = |
837 | SET_RATE_ID(RATR_INX_WIRELESS_G); |
838 | |
839 | } else if (mac->opmode == NL80211_IFTYPE_AP || |
840 | mac->opmode == NL80211_IFTYPE_ADHOC) { |
841 | if (NULL != sta) { |
842 | if (sta->aid > 0) |
843 | tcb_desc->mac_id = sta->aid + 1; |
844 | else |
845 | tcb_desc->mac_id = 1; |
846 | } else { |
847 | tcb_desc->mac_id = 0; |
848 | } |
849 | } |
850 | } |
851 | #undef SET_RATE_ID |
852 | } |
853 | |
854 | static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, |
855 | struct ieee80211_sta *sta, |
856 | struct rtl_tcb_desc *tcb_desc) |
857 | { |
858 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
859 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
860 | |
861 | tcb_desc->packet_bw = false; |
862 | if (!sta) |
863 | return; |
864 | if (mac->opmode == NL80211_IFTYPE_AP || |
865 | mac->opmode == NL80211_IFTYPE_ADHOC || |
866 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { |
867 | if (!(sta->deflink.ht_cap.ht_supported) || |
868 | !(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) |
869 | return; |
870 | } else if (mac->opmode == NL80211_IFTYPE_STATION) { |
871 | if (!mac->bw_40 || !(sta->deflink.ht_cap.ht_supported)) |
872 | return; |
873 | } |
874 | if (tcb_desc->multicast || tcb_desc->broadcast) |
875 | return; |
876 | |
877 | /*use legency rate, shall use 20MHz */ |
878 | if (tcb_desc->hw_rate <= rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]) |
879 | return; |
880 | |
881 | tcb_desc->packet_bw = HT_CHANNEL_WIDTH_20_40; |
882 | |
883 | if (rtlpriv->cfg->spec_ver & RTL_SPEC_SUPPORT_VHT) { |
884 | if (mac->opmode == NL80211_IFTYPE_AP || |
885 | mac->opmode == NL80211_IFTYPE_ADHOC || |
886 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { |
887 | if (!(sta->deflink.vht_cap.vht_supported)) |
888 | return; |
889 | } else if (mac->opmode == NL80211_IFTYPE_STATION) { |
890 | if (!mac->bw_80 || |
891 | !(sta->deflink.vht_cap.vht_supported)) |
892 | return; |
893 | } |
894 | if (tcb_desc->hw_rate <= |
895 | rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS15]) |
896 | return; |
897 | tcb_desc->packet_bw = HT_CHANNEL_WIDTH_80; |
898 | } |
899 | } |
900 | |
901 | static u8 _rtl_get_vht_highest_n_rate(struct ieee80211_hw *hw, |
902 | struct ieee80211_sta *sta) |
903 | { |
904 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
905 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
906 | u8 hw_rate; |
907 | u16 tx_mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.tx_mcs_map); |
908 | |
909 | if ((get_rf_type(rtlphy) == RF_2T2R) && |
910 | (tx_mcs_map & 0x000c) != 0x000c) { |
911 | if ((tx_mcs_map & 0x000c) >> 2 == |
912 | IEEE80211_VHT_MCS_SUPPORT_0_7) |
913 | hw_rate = |
914 | rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS7]; |
915 | else if ((tx_mcs_map & 0x000c) >> 2 == |
916 | IEEE80211_VHT_MCS_SUPPORT_0_8) |
917 | hw_rate = |
918 | rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS8]; |
919 | else |
920 | hw_rate = |
921 | rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS9]; |
922 | } else { |
923 | if ((tx_mcs_map & 0x0003) == |
924 | IEEE80211_VHT_MCS_SUPPORT_0_7) |
925 | hw_rate = |
926 | rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS7]; |
927 | else if ((tx_mcs_map & 0x0003) == |
928 | IEEE80211_VHT_MCS_SUPPORT_0_8) |
929 | hw_rate = |
930 | rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS8]; |
931 | else |
932 | hw_rate = |
933 | rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS9]; |
934 | } |
935 | |
936 | return hw_rate; |
937 | } |
938 | |
939 | static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw, |
940 | struct ieee80211_sta *sta) |
941 | { |
942 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
943 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
944 | u8 hw_rate; |
945 | |
946 | if (get_rf_type(rtlphy) == RF_2T2R && |
947 | sta->deflink.ht_cap.mcs.rx_mask[1] != 0) |
948 | hw_rate = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS15]; |
949 | else |
950 | hw_rate = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS7]; |
951 | |
952 | return hw_rate; |
953 | } |
954 | |
955 | /* mac80211's rate_idx is like this: |
956 | * |
957 | * 2.4G band:rx_status->band == NL80211_BAND_2GHZ |
958 | * |
959 | * B/G rate: |
960 | * (rx_status->flag & RX_FLAG_HT) = 0, |
961 | * DESC_RATE1M-->DESC_RATE54M ==> idx is 0-->11, |
962 | * |
963 | * N rate: |
964 | * (rx_status->flag & RX_FLAG_HT) = 1, |
965 | * DESC_RATEMCS0-->DESC_RATEMCS15 ==> idx is 0-->15 |
966 | * |
967 | * 5G band:rx_status->band == NL80211_BAND_5GHZ |
968 | * A rate: |
969 | * (rx_status->flag & RX_FLAG_HT) = 0, |
970 | * DESC_RATE6M-->DESC_RATE54M ==> idx is 0-->7, |
971 | * |
972 | * N rate: |
973 | * (rx_status->flag & RX_FLAG_HT) = 1, |
974 | * DESC_RATEMCS0-->DESC_RATEMCS15 ==> idx is 0-->15 |
975 | * |
976 | * VHT rates: |
977 | * DESC_RATEVHT1SS_MCS0-->DESC_RATEVHT1SS_MCS9 ==> idx is 0-->9 |
978 | * DESC_RATEVHT2SS_MCS0-->DESC_RATEVHT2SS_MCS9 ==> idx is 0-->9 |
979 | */ |
980 | int rtlwifi_rate_mapping(struct ieee80211_hw *hw, bool isht, bool isvht, |
981 | u8 desc_rate) |
982 | { |
983 | int rate_idx; |
984 | |
985 | if (isvht) { |
986 | switch (desc_rate) { |
987 | case DESC_RATEVHT1SS_MCS0: |
988 | rate_idx = 0; |
989 | break; |
990 | case DESC_RATEVHT1SS_MCS1: |
991 | rate_idx = 1; |
992 | break; |
993 | case DESC_RATEVHT1SS_MCS2: |
994 | rate_idx = 2; |
995 | break; |
996 | case DESC_RATEVHT1SS_MCS3: |
997 | rate_idx = 3; |
998 | break; |
999 | case DESC_RATEVHT1SS_MCS4: |
1000 | rate_idx = 4; |
1001 | break; |
1002 | case DESC_RATEVHT1SS_MCS5: |
1003 | rate_idx = 5; |
1004 | break; |
1005 | case DESC_RATEVHT1SS_MCS6: |
1006 | rate_idx = 6; |
1007 | break; |
1008 | case DESC_RATEVHT1SS_MCS7: |
1009 | rate_idx = 7; |
1010 | break; |
1011 | case DESC_RATEVHT1SS_MCS8: |
1012 | rate_idx = 8; |
1013 | break; |
1014 | case DESC_RATEVHT1SS_MCS9: |
1015 | rate_idx = 9; |
1016 | break; |
1017 | case DESC_RATEVHT2SS_MCS0: |
1018 | rate_idx = 0; |
1019 | break; |
1020 | case DESC_RATEVHT2SS_MCS1: |
1021 | rate_idx = 1; |
1022 | break; |
1023 | case DESC_RATEVHT2SS_MCS2: |
1024 | rate_idx = 2; |
1025 | break; |
1026 | case DESC_RATEVHT2SS_MCS3: |
1027 | rate_idx = 3; |
1028 | break; |
1029 | case DESC_RATEVHT2SS_MCS4: |
1030 | rate_idx = 4; |
1031 | break; |
1032 | case DESC_RATEVHT2SS_MCS5: |
1033 | rate_idx = 5; |
1034 | break; |
1035 | case DESC_RATEVHT2SS_MCS6: |
1036 | rate_idx = 6; |
1037 | break; |
1038 | case DESC_RATEVHT2SS_MCS7: |
1039 | rate_idx = 7; |
1040 | break; |
1041 | case DESC_RATEVHT2SS_MCS8: |
1042 | rate_idx = 8; |
1043 | break; |
1044 | case DESC_RATEVHT2SS_MCS9: |
1045 | rate_idx = 9; |
1046 | break; |
1047 | default: |
1048 | rate_idx = 0; |
1049 | break; |
1050 | } |
1051 | return rate_idx; |
1052 | } |
1053 | if (false == isht) { |
1054 | if (NL80211_BAND_2GHZ == hw->conf.chandef.chan->band) { |
1055 | switch (desc_rate) { |
1056 | case DESC_RATE1M: |
1057 | rate_idx = 0; |
1058 | break; |
1059 | case DESC_RATE2M: |
1060 | rate_idx = 1; |
1061 | break; |
1062 | case DESC_RATE5_5M: |
1063 | rate_idx = 2; |
1064 | break; |
1065 | case DESC_RATE11M: |
1066 | rate_idx = 3; |
1067 | break; |
1068 | case DESC_RATE6M: |
1069 | rate_idx = 4; |
1070 | break; |
1071 | case DESC_RATE9M: |
1072 | rate_idx = 5; |
1073 | break; |
1074 | case DESC_RATE12M: |
1075 | rate_idx = 6; |
1076 | break; |
1077 | case DESC_RATE18M: |
1078 | rate_idx = 7; |
1079 | break; |
1080 | case DESC_RATE24M: |
1081 | rate_idx = 8; |
1082 | break; |
1083 | case DESC_RATE36M: |
1084 | rate_idx = 9; |
1085 | break; |
1086 | case DESC_RATE48M: |
1087 | rate_idx = 10; |
1088 | break; |
1089 | case DESC_RATE54M: |
1090 | rate_idx = 11; |
1091 | break; |
1092 | default: |
1093 | rate_idx = 0; |
1094 | break; |
1095 | } |
1096 | } else { |
1097 | switch (desc_rate) { |
1098 | case DESC_RATE6M: |
1099 | rate_idx = 0; |
1100 | break; |
1101 | case DESC_RATE9M: |
1102 | rate_idx = 1; |
1103 | break; |
1104 | case DESC_RATE12M: |
1105 | rate_idx = 2; |
1106 | break; |
1107 | case DESC_RATE18M: |
1108 | rate_idx = 3; |
1109 | break; |
1110 | case DESC_RATE24M: |
1111 | rate_idx = 4; |
1112 | break; |
1113 | case DESC_RATE36M: |
1114 | rate_idx = 5; |
1115 | break; |
1116 | case DESC_RATE48M: |
1117 | rate_idx = 6; |
1118 | break; |
1119 | case DESC_RATE54M: |
1120 | rate_idx = 7; |
1121 | break; |
1122 | default: |
1123 | rate_idx = 0; |
1124 | break; |
1125 | } |
1126 | } |
1127 | } else { |
1128 | switch (desc_rate) { |
1129 | case DESC_RATEMCS0: |
1130 | rate_idx = 0; |
1131 | break; |
1132 | case DESC_RATEMCS1: |
1133 | rate_idx = 1; |
1134 | break; |
1135 | case DESC_RATEMCS2: |
1136 | rate_idx = 2; |
1137 | break; |
1138 | case DESC_RATEMCS3: |
1139 | rate_idx = 3; |
1140 | break; |
1141 | case DESC_RATEMCS4: |
1142 | rate_idx = 4; |
1143 | break; |
1144 | case DESC_RATEMCS5: |
1145 | rate_idx = 5; |
1146 | break; |
1147 | case DESC_RATEMCS6: |
1148 | rate_idx = 6; |
1149 | break; |
1150 | case DESC_RATEMCS7: |
1151 | rate_idx = 7; |
1152 | break; |
1153 | case DESC_RATEMCS8: |
1154 | rate_idx = 8; |
1155 | break; |
1156 | case DESC_RATEMCS9: |
1157 | rate_idx = 9; |
1158 | break; |
1159 | case DESC_RATEMCS10: |
1160 | rate_idx = 10; |
1161 | break; |
1162 | case DESC_RATEMCS11: |
1163 | rate_idx = 11; |
1164 | break; |
1165 | case DESC_RATEMCS12: |
1166 | rate_idx = 12; |
1167 | break; |
1168 | case DESC_RATEMCS13: |
1169 | rate_idx = 13; |
1170 | break; |
1171 | case DESC_RATEMCS14: |
1172 | rate_idx = 14; |
1173 | break; |
1174 | case DESC_RATEMCS15: |
1175 | rate_idx = 15; |
1176 | break; |
1177 | default: |
1178 | rate_idx = 0; |
1179 | break; |
1180 | } |
1181 | } |
1182 | return rate_idx; |
1183 | } |
1184 | EXPORT_SYMBOL(rtlwifi_rate_mapping); |
1185 | |
1186 | static u8 _rtl_get_tx_hw_rate(struct ieee80211_hw *hw, |
1187 | struct ieee80211_tx_info *info) |
1188 | { |
1189 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1190 | struct ieee80211_tx_rate *r = &info->status.rates[0]; |
1191 | struct ieee80211_rate *txrate; |
1192 | u8 hw_value = 0x0; |
1193 | |
1194 | if (r->flags & IEEE80211_TX_RC_MCS) { |
1195 | /* HT MCS0-15 */ |
1196 | hw_value = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS15] - 15 + |
1197 | r->idx; |
1198 | } else if (r->flags & IEEE80211_TX_RC_VHT_MCS) { |
1199 | /* VHT MCS0-9, NSS */ |
1200 | if (ieee80211_rate_get_vht_nss(rate: r) == 2) |
1201 | hw_value = rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS9]; |
1202 | else |
1203 | hw_value = rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS9]; |
1204 | |
1205 | hw_value = hw_value - 9 + ieee80211_rate_get_vht_mcs(rate: r); |
1206 | } else { |
1207 | /* legacy */ |
1208 | txrate = ieee80211_get_tx_rate(hw, c: info); |
1209 | |
1210 | if (txrate) |
1211 | hw_value = txrate->hw_value; |
1212 | } |
1213 | |
1214 | /* check 5G band */ |
1215 | if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G && |
1216 | hw_value < rtlpriv->cfg->maps[RTL_RC_OFDM_RATE6M]) |
1217 | hw_value = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE6M]; |
1218 | |
1219 | return hw_value; |
1220 | } |
1221 | |
1222 | void rtl_get_tcb_desc(struct ieee80211_hw *hw, |
1223 | struct ieee80211_tx_info *info, |
1224 | struct ieee80211_sta *sta, |
1225 | struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc) |
1226 | { |
1227 | #define SET_RATE_ID(rate_id) \ |
1228 | ({typeof(rate_id) _id = rate_id; \ |
1229 | ((rtlpriv->cfg->spec_ver & RTL_SPEC_NEW_RATEID) ? \ |
1230 | rtl_mrate_idx_to_arfr_id(hw, _id, \ |
1231 | (sta_entry ? sta_entry->wireless_mode : \ |
1232 | WIRELESS_MODE_G)) : \ |
1233 | _id); }) |
1234 | |
1235 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1236 | struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); |
1237 | struct ieee80211_hdr *hdr = rtl_get_hdr(skb); |
1238 | struct rtl_sta_info *sta_entry = |
1239 | (sta ? (struct rtl_sta_info *)sta->drv_priv : NULL); |
1240 | |
1241 | __le16 fc = rtl_get_fc(skb); |
1242 | |
1243 | tcb_desc->hw_rate = _rtl_get_tx_hw_rate(hw, info); |
1244 | |
1245 | if (rtl_is_tx_report_skb(hw, skb)) |
1246 | tcb_desc->use_spe_rpt = 1; |
1247 | |
1248 | if (ieee80211_is_data(fc)) { |
1249 | /* |
1250 | *we set data rate INX 0 |
1251 | *in rtl_rc.c if skb is special data or |
1252 | *mgt which need low data rate. |
1253 | */ |
1254 | |
1255 | /* |
1256 | *So tcb_desc->hw_rate is just used for |
1257 | *special data and mgt frames |
1258 | */ |
1259 | if (info->control.rates[0].idx == 0 || |
1260 | ieee80211_is_nullfunc(fc)) { |
1261 | tcb_desc->use_driver_rate = true; |
1262 | tcb_desc->ratr_index = |
1263 | SET_RATE_ID(RATR_INX_WIRELESS_MC); |
1264 | |
1265 | tcb_desc->disable_ratefallback = 1; |
1266 | } else { |
1267 | /* |
1268 | *because hw will nerver use hw_rate |
1269 | *when tcb_desc->use_driver_rate = false |
1270 | *so we never set highest N rate here, |
1271 | *and N rate will all be controlled by FW |
1272 | *when tcb_desc->use_driver_rate = false |
1273 | */ |
1274 | if (sta && sta->deflink.vht_cap.vht_supported) { |
1275 | tcb_desc->hw_rate = |
1276 | _rtl_get_vht_highest_n_rate(hw, sta); |
1277 | } else { |
1278 | if (sta && sta->deflink.ht_cap.ht_supported) { |
1279 | tcb_desc->hw_rate = |
1280 | _rtl_get_highest_n_rate(hw, sta); |
1281 | } else { |
1282 | if (rtlmac->mode == WIRELESS_MODE_B) { |
1283 | tcb_desc->hw_rate = |
1284 | rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]; |
1285 | } else { |
1286 | tcb_desc->hw_rate = |
1287 | rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]; |
1288 | } |
1289 | } |
1290 | } |
1291 | } |
1292 | |
1293 | if (is_multicast_ether_addr(addr: hdr->addr1)) |
1294 | tcb_desc->multicast = 1; |
1295 | else if (is_broadcast_ether_addr(addr: hdr->addr1)) |
1296 | tcb_desc->broadcast = 1; |
1297 | |
1298 | _rtl_txrate_selectmode(hw, sta, tcb_desc); |
1299 | _rtl_query_bandwidth_mode(hw, sta, tcb_desc); |
1300 | _rtl_qurey_shortpreamble_mode(hw, tcb_desc, info); |
1301 | _rtl_query_shortgi(hw, sta, tcb_desc, info); |
1302 | _rtl_query_protection_mode(hw, tcb_desc, info); |
1303 | } else { |
1304 | tcb_desc->use_driver_rate = true; |
1305 | tcb_desc->ratr_index = SET_RATE_ID(RATR_INX_WIRELESS_MC); |
1306 | tcb_desc->disable_ratefallback = 1; |
1307 | tcb_desc->mac_id = 0; |
1308 | tcb_desc->packet_bw = false; |
1309 | } |
1310 | #undef SET_RATE_ID |
1311 | } |
1312 | EXPORT_SYMBOL(rtl_get_tcb_desc); |
1313 | |
1314 | bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb) |
1315 | { |
1316 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
1317 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1318 | __le16 fc = rtl_get_fc(skb); |
1319 | |
1320 | if (ieee80211_is_auth(fc)) { |
1321 | rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n" ); |
1322 | |
1323 | mac->link_state = MAC80211_LINKING; |
1324 | /* Dul mac */ |
1325 | rtlpriv->phy.need_iqk = true; |
1326 | |
1327 | } |
1328 | |
1329 | return true; |
1330 | } |
1331 | EXPORT_SYMBOL_GPL(rtl_tx_mgmt_proc); |
1332 | |
1333 | struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, u8 *sa, |
1334 | u8 *bssid, u16 tid); |
1335 | |
1336 | static void process_agg_start(struct ieee80211_hw *hw, |
1337 | struct ieee80211_hdr *hdr, u16 tid) |
1338 | { |
1339 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1340 | struct ieee80211_rx_status rx_status = { 0 }; |
1341 | struct sk_buff *skb_delba = NULL; |
1342 | |
1343 | skb_delba = rtl_make_del_ba(hw, sa: hdr->addr2, bssid: hdr->addr3, tid); |
1344 | if (skb_delba) { |
1345 | rx_status.freq = hw->conf.chandef.chan->center_freq; |
1346 | rx_status.band = hw->conf.chandef.chan->band; |
1347 | rx_status.flag |= RX_FLAG_DECRYPTED; |
1348 | rx_status.flag |= RX_FLAG_MACTIME_START; |
1349 | rx_status.rate_idx = 0; |
1350 | rx_status.signal = 50 + 10; |
1351 | memcpy(IEEE80211_SKB_RXCB(skb_delba), |
1352 | &rx_status, sizeof(rx_status)); |
1353 | RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, |
1354 | "fake del\n" , |
1355 | skb_delba->data, |
1356 | skb_delba->len); |
1357 | ieee80211_rx_irqsafe(hw, skb: skb_delba); |
1358 | } |
1359 | } |
1360 | |
1361 | bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) |
1362 | { |
1363 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
1364 | struct ieee80211_hdr *hdr = rtl_get_hdr(skb); |
1365 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1366 | __le16 fc = rtl_get_fc(skb); |
1367 | u8 *act = (u8 *)(((u8 *)skb->data + MAC80211_3ADDR_LEN)); |
1368 | u8 category; |
1369 | |
1370 | if (!ieee80211_is_action(fc)) |
1371 | return true; |
1372 | |
1373 | category = *act; |
1374 | act++; |
1375 | switch (category) { |
1376 | case ACT_CAT_BA: |
1377 | switch (*act) { |
1378 | case ACT_ADDBAREQ: |
1379 | if (mac->act_scanning) |
1380 | return false; |
1381 | |
1382 | rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, |
1383 | "%s ACT_ADDBAREQ From :%pM\n" , |
1384 | is_tx ? "Tx" : "Rx" , hdr->addr2); |
1385 | RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "req\n" , |
1386 | skb->data, skb->len); |
1387 | if (!is_tx) { |
1388 | struct ieee80211_sta *sta = NULL; |
1389 | struct rtl_sta_info *sta_entry = NULL; |
1390 | struct rtl_tid_data *tid_data; |
1391 | struct ieee80211_mgmt *mgmt = (void *)skb->data; |
1392 | u16 capab = 0, tid = 0; |
1393 | |
1394 | rcu_read_lock(); |
1395 | sta = rtl_find_sta(hw, mac_addr: hdr->addr3); |
1396 | if (sta == NULL) { |
1397 | rtl_dbg(rtlpriv, COMP_SEND | COMP_RECV, |
1398 | DBG_DMESG, "sta is NULL\n" ); |
1399 | rcu_read_unlock(); |
1400 | return true; |
1401 | } |
1402 | |
1403 | sta_entry = |
1404 | (struct rtl_sta_info *)sta->drv_priv; |
1405 | capab = |
1406 | le16_to_cpu(mgmt->u.action.u.addba_req.capab); |
1407 | tid = (capab & |
1408 | IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; |
1409 | if (tid >= MAX_TID_COUNT) { |
1410 | rcu_read_unlock(); |
1411 | return true; |
1412 | } |
1413 | tid_data = &sta_entry->tids[tid]; |
1414 | if (tid_data->agg.rx_agg_state == |
1415 | RTL_RX_AGG_START) |
1416 | process_agg_start(hw, hdr, tid); |
1417 | rcu_read_unlock(); |
1418 | } |
1419 | break; |
1420 | case ACT_ADDBARSP: |
1421 | rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, |
1422 | "%s ACT_ADDBARSP From :%pM\n" , |
1423 | is_tx ? "Tx" : "Rx" , hdr->addr2); |
1424 | break; |
1425 | case ACT_DELBA: |
1426 | rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, |
1427 | "ACT_ADDBADEL From :%pM\n" , hdr->addr2); |
1428 | break; |
1429 | } |
1430 | break; |
1431 | default: |
1432 | break; |
1433 | } |
1434 | |
1435 | return true; |
1436 | } |
1437 | EXPORT_SYMBOL_GPL(rtl_action_proc); |
1438 | |
1439 | static void setup_special_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc, |
1440 | int type) |
1441 | { |
1442 | struct ieee80211_hw *hw = rtlpriv->hw; |
1443 | |
1444 | rtlpriv->ra.is_special_data = true; |
1445 | if (rtlpriv->cfg->ops->get_btc_status()) |
1446 | rtlpriv->btcoexist.btc_ops->btc_special_packet_notify( |
1447 | rtlpriv, type); |
1448 | rtl_lps_leave(hw, may_block: false); |
1449 | ppsc->last_delaylps_stamp_jiffies = jiffies; |
1450 | } |
1451 | |
1452 | static const u8 *rtl_skb_ether_type_ptr(struct ieee80211_hw *hw, |
1453 | struct sk_buff *skb, bool is_enc) |
1454 | { |
1455 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1456 | u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb); |
1457 | u8 = 0; |
1458 | u8 offset; |
1459 | |
1460 | switch (rtlpriv->sec.pairwise_enc_algorithm) { |
1461 | case WEP40_ENCRYPTION: |
1462 | case WEP104_ENCRYPTION: |
1463 | encrypt_header_len = 4;/*WEP_IV_LEN*/ |
1464 | break; |
1465 | case TKIP_ENCRYPTION: |
1466 | encrypt_header_len = 8;/*TKIP_IV_LEN*/ |
1467 | break; |
1468 | case AESCCMP_ENCRYPTION: |
1469 | encrypt_header_len = 8;/*CCMP_HDR_LEN;*/ |
1470 | break; |
1471 | default: |
1472 | break; |
1473 | } |
1474 | |
1475 | offset = mac_hdr_len + SNAP_SIZE; |
1476 | if (is_enc) |
1477 | offset += encrypt_header_len; |
1478 | |
1479 | return skb->data + offset; |
1480 | } |
1481 | |
1482 | /*should call before software enc*/ |
1483 | u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx, |
1484 | bool is_enc) |
1485 | { |
1486 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1487 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
1488 | __le16 fc = rtl_get_fc(skb); |
1489 | u16 ether_type; |
1490 | const u8 *ether_type_ptr; |
1491 | const struct iphdr *ip; |
1492 | |
1493 | if (!ieee80211_is_data(fc)) |
1494 | goto end; |
1495 | |
1496 | ether_type_ptr = rtl_skb_ether_type_ptr(hw, skb, is_enc); |
1497 | ether_type = be16_to_cpup(p: (__be16 *)ether_type_ptr); |
1498 | |
1499 | if (ETH_P_IP == ether_type) { |
1500 | ip = (struct iphdr *)((u8 *)ether_type_ptr + |
1501 | PROTOC_TYPE_SIZE); |
1502 | if (IPPROTO_UDP == ip->protocol) { |
1503 | struct udphdr *udp = (struct udphdr *)((u8 *)ip + |
1504 | (ip->ihl << 2)); |
1505 | if (((((u8 *)udp)[1] == 68) && |
1506 | (((u8 *)udp)[3] == 67)) || |
1507 | ((((u8 *)udp)[1] == 67) && |
1508 | (((u8 *)udp)[3] == 68))) { |
1509 | /* 68 : UDP BOOTP client |
1510 | * 67 : UDP BOOTP server |
1511 | */ |
1512 | rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV), |
1513 | DBG_DMESG, "dhcp %s !!\n" , |
1514 | (is_tx) ? "Tx" : "Rx" ); |
1515 | |
1516 | if (is_tx) |
1517 | setup_special_tx(rtlpriv, ppsc, |
1518 | PACKET_DHCP); |
1519 | |
1520 | return true; |
1521 | } |
1522 | } |
1523 | } else if (ETH_P_ARP == ether_type) { |
1524 | if (is_tx) |
1525 | setup_special_tx(rtlpriv, ppsc, PACKET_ARP); |
1526 | |
1527 | return true; |
1528 | } else if (ETH_P_PAE == ether_type) { |
1529 | /* EAPOL is seens as in-4way */ |
1530 | rtlpriv->btcoexist.btc_info.in_4way = true; |
1531 | rtlpriv->btcoexist.btc_info.in_4way_ts = jiffies; |
1532 | |
1533 | rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, |
1534 | "802.1X %s EAPOL pkt!!\n" , (is_tx) ? "Tx" : "Rx" ); |
1535 | |
1536 | if (is_tx) { |
1537 | rtlpriv->ra.is_special_data = true; |
1538 | rtl_lps_leave(hw, may_block: false); |
1539 | ppsc->last_delaylps_stamp_jiffies = jiffies; |
1540 | |
1541 | setup_special_tx(rtlpriv, ppsc, PACKET_EAPOL); |
1542 | } |
1543 | |
1544 | return true; |
1545 | } else if (ETH_P_IPV6 == ether_type) { |
1546 | /* TODO: Handle any IPv6 cases that need special handling. |
1547 | * For now, always return false |
1548 | */ |
1549 | goto end; |
1550 | } |
1551 | |
1552 | end: |
1553 | rtlpriv->ra.is_special_data = false; |
1554 | return false; |
1555 | } |
1556 | EXPORT_SYMBOL_GPL(rtl_is_special_data); |
1557 | |
1558 | void rtl_tx_ackqueue(struct ieee80211_hw *hw, struct sk_buff *skb) |
1559 | { |
1560 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1561 | struct rtl_tx_report *tx_report = &rtlpriv->tx_report; |
1562 | |
1563 | __skb_queue_tail(list: &tx_report->queue, newsk: skb); |
1564 | } |
1565 | EXPORT_SYMBOL_GPL(rtl_tx_ackqueue); |
1566 | |
1567 | static void rtl_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, |
1568 | bool ack) |
1569 | { |
1570 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1571 | struct ieee80211_tx_info *info; |
1572 | |
1573 | info = IEEE80211_SKB_CB(skb); |
1574 | ieee80211_tx_info_clear_status(info); |
1575 | if (ack) { |
1576 | rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_LOUD, |
1577 | "tx report: ack\n" ); |
1578 | info->flags |= IEEE80211_TX_STAT_ACK; |
1579 | } else { |
1580 | rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_LOUD, |
1581 | "tx report: not ack\n" ); |
1582 | info->flags &= ~IEEE80211_TX_STAT_ACK; |
1583 | } |
1584 | ieee80211_tx_status_irqsafe(hw, skb); |
1585 | } |
1586 | |
1587 | bool rtl_is_tx_report_skb(struct ieee80211_hw *hw, struct sk_buff *skb) |
1588 | { |
1589 | u16 ether_type; |
1590 | const u8 *ether_type_ptr; |
1591 | __le16 fc = rtl_get_fc(skb); |
1592 | |
1593 | ether_type_ptr = rtl_skb_ether_type_ptr(hw, skb, is_enc: true); |
1594 | ether_type = be16_to_cpup(p: (__be16 *)ether_type_ptr); |
1595 | |
1596 | if (ether_type == ETH_P_PAE || ieee80211_is_nullfunc(fc)) |
1597 | return true; |
1598 | |
1599 | return false; |
1600 | } |
1601 | |
1602 | static u16 rtl_get_tx_report_sn(struct ieee80211_hw *hw, |
1603 | struct rtlwifi_tx_info *tx_info) |
1604 | { |
1605 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1606 | struct rtl_tx_report *tx_report = &rtlpriv->tx_report; |
1607 | u16 sn; |
1608 | |
1609 | /* SW_DEFINE[11:8] are reserved (driver fills zeros) |
1610 | * SW_DEFINE[7:2] are used by driver |
1611 | * SW_DEFINE[1:0] are reserved for firmware (driver fills zeros) |
1612 | */ |
1613 | sn = (atomic_inc_return(v: &tx_report->sn) & 0x003F) << 2; |
1614 | |
1615 | tx_report->last_sent_sn = sn; |
1616 | tx_report->last_sent_time = jiffies; |
1617 | tx_info->sn = sn; |
1618 | tx_info->send_time = tx_report->last_sent_time; |
1619 | rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_DMESG, |
1620 | "Send TX-Report sn=0x%X\n" , sn); |
1621 | |
1622 | return sn; |
1623 | } |
1624 | |
1625 | void rtl_set_tx_report(struct rtl_tcb_desc *ptcb_desc, u8 *pdesc, |
1626 | struct ieee80211_hw *hw, struct rtlwifi_tx_info *tx_info) |
1627 | { |
1628 | if (ptcb_desc->use_spe_rpt) { |
1629 | u16 sn = rtl_get_tx_report_sn(hw, tx_info); |
1630 | |
1631 | SET_TX_DESC_SPE_RPT(pdesc, 1); |
1632 | SET_TX_DESC_SW_DEFINE(pdesc, sn); |
1633 | } |
1634 | } |
1635 | EXPORT_SYMBOL_GPL(rtl_set_tx_report); |
1636 | |
1637 | void rtl_tx_report_handler(struct ieee80211_hw *hw, u8 *tmp_buf, u8 c2h_cmd_len) |
1638 | { |
1639 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1640 | struct rtl_tx_report *tx_report = &rtlpriv->tx_report; |
1641 | struct rtlwifi_tx_info *tx_info; |
1642 | struct sk_buff_head *queue = &tx_report->queue; |
1643 | struct sk_buff *skb; |
1644 | u16 sn; |
1645 | u8 st, retry; |
1646 | |
1647 | if (rtlpriv->cfg->spec_ver & RTL_SPEC_EXT_C2H) { |
1648 | sn = GET_TX_REPORT_SN_V2(tmp_buf); |
1649 | st = GET_TX_REPORT_ST_V2(tmp_buf); |
1650 | retry = GET_TX_REPORT_RETRY_V2(tmp_buf); |
1651 | } else { |
1652 | sn = GET_TX_REPORT_SN_V1(tmp_buf); |
1653 | st = GET_TX_REPORT_ST_V1(tmp_buf); |
1654 | retry = GET_TX_REPORT_RETRY_V1(tmp_buf); |
1655 | } |
1656 | |
1657 | tx_report->last_recv_sn = sn; |
1658 | |
1659 | skb_queue_walk(queue, skb) { |
1660 | tx_info = rtl_tx_skb_cb_info(skb); |
1661 | if (tx_info->sn == sn) { |
1662 | skb_unlink(skb, list: queue); |
1663 | rtl_tx_status(hw, skb, ack: st == 0); |
1664 | break; |
1665 | } |
1666 | } |
1667 | rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_DMESG, |
1668 | "Recv TX-Report st=0x%02X sn=0x%X retry=0x%X\n" , |
1669 | st, sn, retry); |
1670 | } |
1671 | EXPORT_SYMBOL_GPL(rtl_tx_report_handler); |
1672 | |
1673 | bool rtl_check_tx_report_acked(struct ieee80211_hw *hw) |
1674 | { |
1675 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1676 | struct rtl_tx_report *tx_report = &rtlpriv->tx_report; |
1677 | |
1678 | if (tx_report->last_sent_sn == tx_report->last_recv_sn) |
1679 | return true; |
1680 | |
1681 | if (time_before(tx_report->last_sent_time + 3 * HZ, jiffies)) { |
1682 | rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_WARNING, |
1683 | "Check TX-Report timeout!! s_sn=0x%X r_sn=0x%X\n" , |
1684 | tx_report->last_sent_sn, tx_report->last_recv_sn); |
1685 | return true; /* 3 sec. (timeout) seen as acked */ |
1686 | } |
1687 | |
1688 | return false; |
1689 | } |
1690 | |
1691 | void rtl_wait_tx_report_acked(struct ieee80211_hw *hw, u32 wait_ms) |
1692 | { |
1693 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1694 | int i; |
1695 | |
1696 | for (i = 0; i < wait_ms; i++) { |
1697 | if (rtl_check_tx_report_acked(hw)) |
1698 | break; |
1699 | usleep_range(min: 1000, max: 2000); |
1700 | rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, |
1701 | "Wait 1ms (%d/%d) to disable key.\n" , i, wait_ms); |
1702 | } |
1703 | } |
1704 | |
1705 | u32 rtl_get_hal_edca_param(struct ieee80211_hw *hw, |
1706 | struct ieee80211_vif *vif, |
1707 | enum wireless_mode wirelessmode, |
1708 | struct ieee80211_tx_queue_params *param) |
1709 | { |
1710 | u32 reg = 0; |
1711 | u8 sifstime = 10; |
1712 | u8 slottime = 20; |
1713 | |
1714 | /* AIFS = AIFSN * slot time + SIFS */ |
1715 | switch (wirelessmode) { |
1716 | case WIRELESS_MODE_A: |
1717 | case WIRELESS_MODE_N_24G: |
1718 | case WIRELESS_MODE_N_5G: |
1719 | case WIRELESS_MODE_AC_5G: |
1720 | case WIRELESS_MODE_AC_24G: |
1721 | sifstime = 16; |
1722 | slottime = 9; |
1723 | break; |
1724 | case WIRELESS_MODE_G: |
1725 | slottime = (vif->bss_conf.use_short_slot ? 9 : 20); |
1726 | break; |
1727 | default: |
1728 | break; |
1729 | } |
1730 | |
1731 | reg |= (param->txop & 0x7FF) << 16; |
1732 | reg |= (fls(x: param->cw_max) & 0xF) << 12; |
1733 | reg |= (fls(x: param->cw_min) & 0xF) << 8; |
1734 | reg |= (param->aifs & 0x0F) * slottime + sifstime; |
1735 | |
1736 | return reg; |
1737 | } |
1738 | EXPORT_SYMBOL_GPL(rtl_get_hal_edca_param); |
1739 | |
1740 | /********************************************************* |
1741 | * |
1742 | * functions called by core.c |
1743 | * |
1744 | *********************************************************/ |
1745 | int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1746 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
1747 | { |
1748 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1749 | struct rtl_tid_data *tid_data; |
1750 | struct rtl_sta_info *sta_entry = NULL; |
1751 | |
1752 | if (sta == NULL) |
1753 | return -EINVAL; |
1754 | |
1755 | if (unlikely(tid >= MAX_TID_COUNT)) |
1756 | return -EINVAL; |
1757 | |
1758 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; |
1759 | tid_data = &sta_entry->tids[tid]; |
1760 | |
1761 | rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG, |
1762 | "on ra = %pM tid = %d seq:%d\n" , sta->addr, tid, |
1763 | *ssn); |
1764 | |
1765 | tid_data->agg.agg_state = RTL_AGG_START; |
1766 | |
1767 | return IEEE80211_AMPDU_TX_START_IMMEDIATE; |
1768 | } |
1769 | |
1770 | int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1771 | struct ieee80211_sta *sta, u16 tid) |
1772 | { |
1773 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1774 | struct rtl_sta_info *sta_entry = NULL; |
1775 | |
1776 | if (sta == NULL) |
1777 | return -EINVAL; |
1778 | |
1779 | rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG, |
1780 | "on ra = %pM tid = %d\n" , sta->addr, tid); |
1781 | |
1782 | if (unlikely(tid >= MAX_TID_COUNT)) |
1783 | return -EINVAL; |
1784 | |
1785 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; |
1786 | sta_entry->tids[tid].agg.agg_state = RTL_AGG_STOP; |
1787 | |
1788 | ieee80211_stop_tx_ba_cb_irqsafe(vif, ra: sta->addr, tid); |
1789 | return 0; |
1790 | } |
1791 | |
1792 | int rtl_rx_agg_start(struct ieee80211_hw *hw, |
1793 | struct ieee80211_sta *sta, u16 tid) |
1794 | { |
1795 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1796 | struct rtl_tid_data *tid_data; |
1797 | struct rtl_sta_info *sta_entry = NULL; |
1798 | u8 reject_agg; |
1799 | |
1800 | if (sta == NULL) |
1801 | return -EINVAL; |
1802 | |
1803 | if (unlikely(tid >= MAX_TID_COUNT)) |
1804 | return -EINVAL; |
1805 | |
1806 | if (rtlpriv->cfg->ops->get_btc_status()) { |
1807 | rtlpriv->btcoexist.btc_ops->btc_get_ampdu_cfg(rtlpriv, |
1808 | &reject_agg, |
1809 | NULL, NULL); |
1810 | if (reject_agg) |
1811 | return -EINVAL; |
1812 | } |
1813 | |
1814 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; |
1815 | tid_data = &sta_entry->tids[tid]; |
1816 | |
1817 | rtl_dbg(rtlpriv, COMP_RECV, DBG_DMESG, |
1818 | "on ra = %pM tid = %d\n" , sta->addr, tid); |
1819 | |
1820 | tid_data->agg.rx_agg_state = RTL_RX_AGG_START; |
1821 | return 0; |
1822 | } |
1823 | |
1824 | int rtl_rx_agg_stop(struct ieee80211_hw *hw, |
1825 | struct ieee80211_sta *sta, u16 tid) |
1826 | { |
1827 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1828 | struct rtl_sta_info *sta_entry = NULL; |
1829 | |
1830 | if (sta == NULL) |
1831 | return -EINVAL; |
1832 | |
1833 | rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG, |
1834 | "on ra = %pM tid = %d\n" , sta->addr, tid); |
1835 | |
1836 | if (unlikely(tid >= MAX_TID_COUNT)) |
1837 | return -EINVAL; |
1838 | |
1839 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; |
1840 | sta_entry->tids[tid].agg.rx_agg_state = RTL_RX_AGG_STOP; |
1841 | |
1842 | return 0; |
1843 | } |
1844 | |
1845 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, |
1846 | struct ieee80211_sta *sta, u16 tid) |
1847 | { |
1848 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1849 | struct rtl_sta_info *sta_entry = NULL; |
1850 | |
1851 | if (sta == NULL) |
1852 | return -EINVAL; |
1853 | |
1854 | rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG, |
1855 | "on ra = %pM tid = %d\n" , sta->addr, tid); |
1856 | |
1857 | if (unlikely(tid >= MAX_TID_COUNT)) |
1858 | return -EINVAL; |
1859 | |
1860 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; |
1861 | sta_entry->tids[tid].agg.agg_state = RTL_AGG_OPERATIONAL; |
1862 | |
1863 | return 0; |
1864 | } |
1865 | |
1866 | void rtl_rx_ampdu_apply(struct rtl_priv *rtlpriv) |
1867 | { |
1868 | struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops; |
1869 | u8 reject_agg = 0, ctrl_agg_size = 0, agg_size = 0; |
1870 | |
1871 | if (rtlpriv->cfg->ops->get_btc_status()) |
1872 | btc_ops->btc_get_ampdu_cfg(rtlpriv, &reject_agg, |
1873 | &ctrl_agg_size, &agg_size); |
1874 | |
1875 | rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, |
1876 | "Set RX AMPDU: coex - reject=%d, ctrl_agg_size=%d, size=%d" , |
1877 | reject_agg, ctrl_agg_size, agg_size); |
1878 | |
1879 | rtlpriv->hw->max_rx_aggregation_subframes = |
1880 | (ctrl_agg_size ? agg_size : IEEE80211_MAX_AMPDU_BUF_HT); |
1881 | } |
1882 | EXPORT_SYMBOL(rtl_rx_ampdu_apply); |
1883 | |
1884 | /********************************************************* |
1885 | * |
1886 | * wq & timer callback functions |
1887 | * |
1888 | *********************************************************/ |
1889 | /* this function is used for roaming */ |
1890 | void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb) |
1891 | { |
1892 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1893 | struct ieee80211_hdr *hdr = rtl_get_hdr(skb); |
1894 | |
1895 | if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) |
1896 | return; |
1897 | |
1898 | if (rtlpriv->mac80211.link_state < MAC80211_LINKED) |
1899 | return; |
1900 | |
1901 | /* check if this really is a beacon */ |
1902 | if (!ieee80211_is_beacon(fc: hdr->frame_control) && |
1903 | !ieee80211_is_probe_resp(fc: hdr->frame_control)) |
1904 | return; |
1905 | |
1906 | /* min. beacon length + FCS_LEN */ |
1907 | if (skb->len <= 40 + FCS_LEN) |
1908 | return; |
1909 | |
1910 | /* and only beacons from the associated BSSID, please */ |
1911 | if (!ether_addr_equal(addr1: hdr->addr3, addr2: rtlpriv->mac80211.bssid)) |
1912 | return; |
1913 | |
1914 | rtlpriv->link_info.bcn_rx_inperiod++; |
1915 | } |
1916 | EXPORT_SYMBOL_GPL(rtl_beacon_statistic); |
1917 | |
1918 | static void rtl_free_entries_from_scan_list(struct ieee80211_hw *hw) |
1919 | { |
1920 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1921 | struct rtl_bssid_entry *entry, *next; |
1922 | |
1923 | list_for_each_entry_safe(entry, next, &rtlpriv->scan_list.list, list) { |
1924 | list_del(entry: &entry->list); |
1925 | kfree(objp: entry); |
1926 | rtlpriv->scan_list.num--; |
1927 | } |
1928 | } |
1929 | |
1930 | static void rtl_free_entries_from_ack_queue(struct ieee80211_hw *hw, |
1931 | bool chk_timeout) |
1932 | { |
1933 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1934 | struct rtl_tx_report *tx_report = &rtlpriv->tx_report; |
1935 | struct sk_buff_head *queue = &tx_report->queue; |
1936 | struct sk_buff *skb, *tmp; |
1937 | struct rtlwifi_tx_info *tx_info; |
1938 | |
1939 | skb_queue_walk_safe(queue, skb, tmp) { |
1940 | tx_info = rtl_tx_skb_cb_info(skb); |
1941 | if (chk_timeout && |
1942 | time_after(tx_info->send_time + HZ, jiffies)) |
1943 | continue; |
1944 | skb_unlink(skb, list: queue); |
1945 | rtl_tx_status(hw, skb, ack: false); |
1946 | } |
1947 | } |
1948 | |
1949 | void rtl_scan_list_expire(struct ieee80211_hw *hw) |
1950 | { |
1951 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1952 | struct rtl_bssid_entry *entry, *next; |
1953 | unsigned long flags; |
1954 | |
1955 | spin_lock_irqsave(&rtlpriv->locks.scan_list_lock, flags); |
1956 | |
1957 | list_for_each_entry_safe(entry, next, &rtlpriv->scan_list.list, list) { |
1958 | /* 180 seconds */ |
1959 | if (jiffies_to_msecs(j: jiffies - entry->age) < 180000) |
1960 | continue; |
1961 | |
1962 | list_del(entry: &entry->list); |
1963 | rtlpriv->scan_list.num--; |
1964 | |
1965 | rtl_dbg(rtlpriv, COMP_SCAN, DBG_LOUD, |
1966 | "BSSID=%pM is expire in scan list (total=%d)\n" , |
1967 | entry->bssid, rtlpriv->scan_list.num); |
1968 | kfree(objp: entry); |
1969 | } |
1970 | |
1971 | spin_unlock_irqrestore(lock: &rtlpriv->locks.scan_list_lock, flags); |
1972 | |
1973 | rtlpriv->btcoexist.btc_info.ap_num = rtlpriv->scan_list.num; |
1974 | } |
1975 | |
1976 | void rtl_collect_scan_list(struct ieee80211_hw *hw, struct sk_buff *skb) |
1977 | { |
1978 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1979 | struct ieee80211_hdr *hdr = rtl_get_hdr(skb); |
1980 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
1981 | unsigned long flags; |
1982 | |
1983 | struct rtl_bssid_entry *entry = NULL, *iter; |
1984 | |
1985 | /* check if it is scanning */ |
1986 | if (!mac->act_scanning) |
1987 | return; |
1988 | |
1989 | /* check if this really is a beacon */ |
1990 | if (!ieee80211_is_beacon(fc: hdr->frame_control) && |
1991 | !ieee80211_is_probe_resp(fc: hdr->frame_control)) |
1992 | return; |
1993 | |
1994 | spin_lock_irqsave(&rtlpriv->locks.scan_list_lock, flags); |
1995 | |
1996 | list_for_each_entry(iter, &rtlpriv->scan_list.list, list) { |
1997 | if (memcmp(p: iter->bssid, q: hdr->addr3, ETH_ALEN) == 0) { |
1998 | list_del_init(entry: &iter->list); |
1999 | entry = iter; |
2000 | rtl_dbg(rtlpriv, COMP_SCAN, DBG_LOUD, |
2001 | "Update BSSID=%pM to scan list (total=%d)\n" , |
2002 | hdr->addr3, rtlpriv->scan_list.num); |
2003 | break; |
2004 | } |
2005 | } |
2006 | |
2007 | if (!entry) { |
2008 | entry = kmalloc(size: sizeof(*entry), GFP_ATOMIC); |
2009 | |
2010 | if (!entry) |
2011 | goto label_err; |
2012 | |
2013 | memcpy(entry->bssid, hdr->addr3, ETH_ALEN); |
2014 | rtlpriv->scan_list.num++; |
2015 | |
2016 | rtl_dbg(rtlpriv, COMP_SCAN, DBG_LOUD, |
2017 | "Add BSSID=%pM to scan list (total=%d)\n" , |
2018 | hdr->addr3, rtlpriv->scan_list.num); |
2019 | } |
2020 | |
2021 | entry->age = jiffies; |
2022 | |
2023 | list_add_tail(new: &entry->list, head: &rtlpriv->scan_list.list); |
2024 | |
2025 | label_err: |
2026 | spin_unlock_irqrestore(lock: &rtlpriv->locks.scan_list_lock, flags); |
2027 | } |
2028 | EXPORT_SYMBOL(rtl_collect_scan_list); |
2029 | |
2030 | static void rtl_watchdog_wq_callback(struct work_struct *work) |
2031 | { |
2032 | struct rtl_works *rtlworks = container_of(work, struct rtl_works, |
2033 | watchdog_wq.work); |
2034 | struct ieee80211_hw *hw = rtlworks->hw; |
2035 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
2036 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
2037 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
2038 | bool busytraffic = false; |
2039 | bool tx_busy_traffic = false; |
2040 | bool rx_busy_traffic = false; |
2041 | bool higher_busytraffic = false; |
2042 | bool higher_busyrxtraffic = false; |
2043 | u8 idx, tid; |
2044 | u32 rx_cnt_inp4eriod = 0; |
2045 | u32 tx_cnt_inp4eriod = 0; |
2046 | u32 aver_rx_cnt_inperiod = 0; |
2047 | u32 aver_tx_cnt_inperiod = 0; |
2048 | u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; |
2049 | u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; |
2050 | |
2051 | if (is_hal_stop(rtlhal)) |
2052 | return; |
2053 | |
2054 | /* <1> Determine if action frame is allowed */ |
2055 | if (mac->link_state > MAC80211_NOLINK) { |
2056 | if (mac->cnt_after_linked < 20) |
2057 | mac->cnt_after_linked++; |
2058 | } else { |
2059 | mac->cnt_after_linked = 0; |
2060 | } |
2061 | |
2062 | /* <2> to check if traffic busy, if |
2063 | * busytraffic we don't change channel |
2064 | */ |
2065 | if (mac->link_state >= MAC80211_LINKED) { |
2066 | /* (1) get aver_rx_cnt_inperiod & aver_tx_cnt_inperiod */ |
2067 | for (idx = 0; idx <= 2; idx++) { |
2068 | rtlpriv->link_info.num_rx_in4period[idx] = |
2069 | rtlpriv->link_info.num_rx_in4period[idx + 1]; |
2070 | rtlpriv->link_info.num_tx_in4period[idx] = |
2071 | rtlpriv->link_info.num_tx_in4period[idx + 1]; |
2072 | } |
2073 | rtlpriv->link_info.num_rx_in4period[3] = |
2074 | rtlpriv->link_info.num_rx_inperiod; |
2075 | rtlpriv->link_info.num_tx_in4period[3] = |
2076 | rtlpriv->link_info.num_tx_inperiod; |
2077 | for (idx = 0; idx <= 3; idx++) { |
2078 | rx_cnt_inp4eriod += |
2079 | rtlpriv->link_info.num_rx_in4period[idx]; |
2080 | tx_cnt_inp4eriod += |
2081 | rtlpriv->link_info.num_tx_in4period[idx]; |
2082 | } |
2083 | aver_rx_cnt_inperiod = rx_cnt_inp4eriod / 4; |
2084 | aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4; |
2085 | |
2086 | /* (2) check traffic busy */ |
2087 | if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) { |
2088 | busytraffic = true; |
2089 | if (aver_rx_cnt_inperiod > aver_tx_cnt_inperiod) |
2090 | rx_busy_traffic = true; |
2091 | else |
2092 | tx_busy_traffic = false; |
2093 | } |
2094 | |
2095 | /* Higher Tx/Rx data. */ |
2096 | if (aver_rx_cnt_inperiod > 4000 || |
2097 | aver_tx_cnt_inperiod > 4000) { |
2098 | higher_busytraffic = true; |
2099 | |
2100 | /* Extremely high Rx data. */ |
2101 | if (aver_rx_cnt_inperiod > 5000) |
2102 | higher_busyrxtraffic = true; |
2103 | } |
2104 | |
2105 | /* check every tid's tx traffic */ |
2106 | for (tid = 0; tid <= 7; tid++) { |
2107 | for (idx = 0; idx <= 2; idx++) |
2108 | rtlpriv->link_info.tidtx_in4period[tid][idx] = |
2109 | rtlpriv->link_info.tidtx_in4period[tid] |
2110 | [idx + 1]; |
2111 | rtlpriv->link_info.tidtx_in4period[tid][3] = |
2112 | rtlpriv->link_info.tidtx_inperiod[tid]; |
2113 | |
2114 | for (idx = 0; idx <= 3; idx++) |
2115 | tidtx_inp4eriod[tid] += |
2116 | rtlpriv->link_info.tidtx_in4period[tid][idx]; |
2117 | aver_tidtx_inperiod[tid] = tidtx_inp4eriod[tid] / 4; |
2118 | if (aver_tidtx_inperiod[tid] > 5000) |
2119 | rtlpriv->link_info.higher_busytxtraffic[tid] = |
2120 | true; |
2121 | else |
2122 | rtlpriv->link_info.higher_busytxtraffic[tid] = |
2123 | false; |
2124 | } |
2125 | |
2126 | /* PS is controlled by coex. */ |
2127 | if (rtlpriv->cfg->ops->get_btc_status() && |
2128 | rtlpriv->btcoexist.btc_ops->btc_is_bt_ctrl_lps(rtlpriv)) |
2129 | goto label_lps_done; |
2130 | |
2131 | if (rtlpriv->link_info.num_rx_inperiod + |
2132 | rtlpriv->link_info.num_tx_inperiod > 8 || |
2133 | rtlpriv->link_info.num_rx_inperiod > 2) |
2134 | rtl_lps_leave(hw, may_block: true); |
2135 | else |
2136 | rtl_lps_enter(hw, may_block: true); |
2137 | |
2138 | label_lps_done: |
2139 | ; |
2140 | } |
2141 | |
2142 | for (tid = 0; tid <= 7; tid++) |
2143 | rtlpriv->link_info.tidtx_inperiod[tid] = 0; |
2144 | |
2145 | rtlpriv->link_info.busytraffic = busytraffic; |
2146 | rtlpriv->link_info.higher_busytraffic = higher_busytraffic; |
2147 | rtlpriv->link_info.rx_busy_traffic = rx_busy_traffic; |
2148 | rtlpriv->link_info.tx_busy_traffic = tx_busy_traffic; |
2149 | rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; |
2150 | |
2151 | rtlpriv->stats.txbytesunicast_inperiod = |
2152 | rtlpriv->stats.txbytesunicast - |
2153 | rtlpriv->stats.txbytesunicast_last; |
2154 | rtlpriv->stats.rxbytesunicast_inperiod = |
2155 | rtlpriv->stats.rxbytesunicast - |
2156 | rtlpriv->stats.rxbytesunicast_last; |
2157 | rtlpriv->stats.txbytesunicast_last = rtlpriv->stats.txbytesunicast; |
2158 | rtlpriv->stats.rxbytesunicast_last = rtlpriv->stats.rxbytesunicast; |
2159 | |
2160 | rtlpriv->stats.txbytesunicast_inperiod_tp = |
2161 | (u32)(rtlpriv->stats.txbytesunicast_inperiod * 8 / 2 / |
2162 | 1024 / 1024); |
2163 | rtlpriv->stats.rxbytesunicast_inperiod_tp = |
2164 | (u32)(rtlpriv->stats.rxbytesunicast_inperiod * 8 / 2 / |
2165 | 1024 / 1024); |
2166 | |
2167 | /* <3> DM */ |
2168 | if (!rtlpriv->cfg->mod_params->disable_watchdog) |
2169 | rtlpriv->cfg->ops->dm_watchdog(hw); |
2170 | |
2171 | /* <4> roaming */ |
2172 | if (mac->link_state == MAC80211_LINKED && |
2173 | mac->opmode == NL80211_IFTYPE_STATION) { |
2174 | if ((rtlpriv->link_info.bcn_rx_inperiod + |
2175 | rtlpriv->link_info.num_rx_inperiod) == 0) { |
2176 | rtlpriv->link_info.roam_times++; |
2177 | rtl_dbg(rtlpriv, COMP_ERR, DBG_DMESG, |
2178 | "AP off for %d s\n" , |
2179 | (rtlpriv->link_info.roam_times * 2)); |
2180 | |
2181 | /* if we can't recv beacon for 10s, |
2182 | * we should reconnect this AP |
2183 | */ |
2184 | if (rtlpriv->link_info.roam_times >= 5) { |
2185 | pr_err("AP off, try to reconnect now\n" ); |
2186 | rtlpriv->link_info.roam_times = 0; |
2187 | ieee80211_connection_loss( |
2188 | vif: rtlpriv->mac80211.vif); |
2189 | } |
2190 | } else { |
2191 | rtlpriv->link_info.roam_times = 0; |
2192 | } |
2193 | } |
2194 | |
2195 | if (rtlpriv->cfg->ops->get_btc_status()) |
2196 | rtlpriv->btcoexist.btc_ops->btc_periodical(rtlpriv); |
2197 | |
2198 | if (rtlpriv->btcoexist.btc_info.in_4way) { |
2199 | if (time_after(jiffies, rtlpriv->btcoexist.btc_info.in_4way_ts + |
2200 | msecs_to_jiffies(IN_4WAY_TIMEOUT_TIME))) |
2201 | rtlpriv->btcoexist.btc_info.in_4way = false; |
2202 | } |
2203 | |
2204 | rtlpriv->link_info.num_rx_inperiod = 0; |
2205 | rtlpriv->link_info.num_tx_inperiod = 0; |
2206 | rtlpriv->link_info.bcn_rx_inperiod = 0; |
2207 | |
2208 | /* <6> scan list */ |
2209 | rtl_scan_list_expire(hw); |
2210 | |
2211 | /* <7> check ack queue */ |
2212 | rtl_free_entries_from_ack_queue(hw, chk_timeout: true); |
2213 | } |
2214 | |
2215 | void rtl_watch_dog_timer_callback(struct timer_list *t) |
2216 | { |
2217 | struct rtl_priv *rtlpriv = from_timer(rtlpriv, t, works.watchdog_timer); |
2218 | |
2219 | queue_delayed_work(wq: rtlpriv->works.rtl_wq, |
2220 | dwork: &rtlpriv->works.watchdog_wq, delay: 0); |
2221 | |
2222 | mod_timer(timer: &rtlpriv->works.watchdog_timer, |
2223 | expires: jiffies + MSECS(RTL_WATCH_DOG_TIME)); |
2224 | } |
2225 | |
2226 | static void rtl_fwevt_wq_callback(struct work_struct *work) |
2227 | { |
2228 | struct rtl_works *rtlworks = container_of(work, struct rtl_works, |
2229 | fwevt_wq.work); |
2230 | struct ieee80211_hw *hw = rtlworks->hw; |
2231 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
2232 | |
2233 | rtlpriv->cfg->ops->c2h_command_handle(hw); |
2234 | } |
2235 | |
2236 | static void rtl_c2h_content_parsing(struct ieee80211_hw *hw, |
2237 | struct sk_buff *skb); |
2238 | |
2239 | static bool rtl_c2h_fast_cmd(struct ieee80211_hw *hw, struct sk_buff *skb) |
2240 | { |
2241 | u8 cmd_id = GET_C2H_CMD_ID(skb->data); |
2242 | |
2243 | switch (cmd_id) { |
2244 | case C2H_BT_MP: |
2245 | return true; |
2246 | default: |
2247 | break; |
2248 | } |
2249 | |
2250 | return false; |
2251 | } |
2252 | |
2253 | void rtl_c2hcmd_enqueue(struct ieee80211_hw *hw, struct sk_buff *skb) |
2254 | { |
2255 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
2256 | |
2257 | if (rtl_c2h_fast_cmd(hw, skb)) { |
2258 | rtl_c2h_content_parsing(hw, skb); |
2259 | kfree_skb(skb); |
2260 | return; |
2261 | } |
2262 | |
2263 | /* enqueue */ |
2264 | skb_queue_tail(list: &rtlpriv->c2hcmd_queue, newsk: skb); |
2265 | |
2266 | /* wake up wq */ |
2267 | queue_delayed_work(wq: rtlpriv->works.rtl_wq, dwork: &rtlpriv->works.c2hcmd_wq, delay: 0); |
2268 | } |
2269 | EXPORT_SYMBOL(rtl_c2hcmd_enqueue); |
2270 | |
2271 | static void rtl_c2h_content_parsing(struct ieee80211_hw *hw, |
2272 | struct sk_buff *skb) |
2273 | { |
2274 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
2275 | struct rtl_hal_ops *hal_ops = rtlpriv->cfg->ops; |
2276 | const struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops; |
2277 | u8 cmd_id, cmd_len; |
2278 | u8 *cmd_buf = NULL; |
2279 | |
2280 | cmd_id = GET_C2H_CMD_ID(skb->data); |
2281 | cmd_len = skb->len - C2H_DATA_OFFSET; |
2282 | cmd_buf = GET_C2H_DATA_PTR(skb->data); |
2283 | |
2284 | switch (cmd_id) { |
2285 | case C2H_DBG: |
2286 | rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "[C2H], C2H_DBG!!\n" ); |
2287 | break; |
2288 | case C2H_TXBF: |
2289 | rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, |
2290 | "[C2H], C2H_TXBF!!\n" ); |
2291 | break; |
2292 | case C2H_TX_REPORT: |
2293 | rtl_tx_report_handler(hw, cmd_buf, cmd_len); |
2294 | break; |
2295 | case C2H_RA_RPT: |
2296 | if (hal_ops->c2h_ra_report_handler) |
2297 | hal_ops->c2h_ra_report_handler(hw, cmd_buf, cmd_len); |
2298 | break; |
2299 | case C2H_BT_INFO: |
2300 | rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, |
2301 | "[C2H], C2H_BT_INFO!!\n" ); |
2302 | if (rtlpriv->cfg->ops->get_btc_status()) |
2303 | btc_ops->btc_btinfo_notify(rtlpriv, cmd_buf, cmd_len); |
2304 | break; |
2305 | case C2H_BT_MP: |
2306 | rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, |
2307 | "[C2H], C2H_BT_MP!!\n" ); |
2308 | if (rtlpriv->cfg->ops->get_btc_status()) |
2309 | btc_ops->btc_btmpinfo_notify(rtlpriv, cmd_buf, cmd_len); |
2310 | break; |
2311 | default: |
2312 | rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, |
2313 | "[C2H], Unknown packet!! cmd_id(%#X)!\n" , cmd_id); |
2314 | break; |
2315 | } |
2316 | } |
2317 | |
2318 | void rtl_c2hcmd_launcher(struct ieee80211_hw *hw, int exec) |
2319 | { |
2320 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
2321 | struct sk_buff *skb; |
2322 | int i; |
2323 | |
2324 | for (i = 0; i < 200; i++) { |
2325 | /* dequeue a task */ |
2326 | skb = skb_dequeue(list: &rtlpriv->c2hcmd_queue); |
2327 | |
2328 | /* do it */ |
2329 | if (!skb) |
2330 | break; |
2331 | |
2332 | rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG, "C2H rx_desc_shift=%d\n" , |
2333 | *((u8 *)skb->cb)); |
2334 | RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_DMESG, |
2335 | "C2H data: " , skb->data, skb->len); |
2336 | |
2337 | if (exec) |
2338 | rtl_c2h_content_parsing(hw, skb); |
2339 | |
2340 | /* free */ |
2341 | dev_kfree_skb_any(skb); |
2342 | } |
2343 | } |
2344 | |
2345 | static void rtl_c2hcmd_wq_callback(struct work_struct *work) |
2346 | { |
2347 | struct rtl_works *rtlworks = container_of(work, struct rtl_works, |
2348 | c2hcmd_wq.work); |
2349 | struct ieee80211_hw *hw = rtlworks->hw; |
2350 | |
2351 | rtl_c2hcmd_launcher(hw, exec: 1); |
2352 | } |
2353 | |
2354 | /********************************************************* |
2355 | * |
2356 | * frame process functions |
2357 | * |
2358 | *********************************************************/ |
2359 | u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie) |
2360 | { |
2361 | struct ieee80211_mgmt *mgmt = (void *)data; |
2362 | u8 *pos, *end; |
2363 | |
2364 | pos = (u8 *)mgmt->u.beacon.variable; |
2365 | end = data + len; |
2366 | while (pos < end) { |
2367 | if (pos + 2 + pos[1] > end) |
2368 | return NULL; |
2369 | |
2370 | if (pos[0] == ie) |
2371 | return pos; |
2372 | |
2373 | pos += 2 + pos[1]; |
2374 | } |
2375 | return NULL; |
2376 | } |
2377 | |
2378 | /* when we use 2 rx ants we send IEEE80211_SMPS_OFF */ |
2379 | /* when we use 1 rx ant we send IEEE80211_SMPS_STATIC */ |
2380 | static struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw, |
2381 | enum ieee80211_smps_mode smps, |
2382 | u8 *da, u8 *bssid) |
2383 | { |
2384 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
2385 | struct sk_buff *skb; |
2386 | struct ieee80211_mgmt *action_frame; |
2387 | |
2388 | /* 27 = header + category + action + smps mode */ |
2389 | skb = dev_alloc_skb(length: 27 + hw->extra_tx_headroom); |
2390 | if (!skb) |
2391 | return NULL; |
2392 | |
2393 | skb_reserve(skb, len: hw->extra_tx_headroom); |
2394 | action_frame = skb_put_zero(skb, len: 27); |
2395 | memcpy(action_frame->da, da, ETH_ALEN); |
2396 | memcpy(action_frame->sa, rtlefuse->dev_addr, ETH_ALEN); |
2397 | memcpy(action_frame->bssid, bssid, ETH_ALEN); |
2398 | action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
2399 | IEEE80211_STYPE_ACTION); |
2400 | action_frame->u.action.category = WLAN_CATEGORY_HT; |
2401 | action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS; |
2402 | switch (smps) { |
2403 | case IEEE80211_SMPS_AUTOMATIC:/* 0 */ |
2404 | case IEEE80211_SMPS_NUM_MODES:/* 4 */ |
2405 | WARN_ON(1); |
2406 | fallthrough; |
2407 | case IEEE80211_SMPS_OFF:/* 1 */ /*MIMO_PS_NOLIMIT*/ |
2408 | action_frame->u.action.u.ht_smps.smps_control = |
2409 | WLAN_HT_SMPS_CONTROL_DISABLED;/* 0 */ |
2410 | break; |
2411 | case IEEE80211_SMPS_STATIC:/* 2 */ /*MIMO_PS_STATIC*/ |
2412 | action_frame->u.action.u.ht_smps.smps_control = |
2413 | WLAN_HT_SMPS_CONTROL_STATIC;/* 1 */ |
2414 | break; |
2415 | case IEEE80211_SMPS_DYNAMIC:/* 3 */ /*MIMO_PS_DYNAMIC*/ |
2416 | action_frame->u.action.u.ht_smps.smps_control = |
2417 | WLAN_HT_SMPS_CONTROL_DYNAMIC;/* 3 */ |
2418 | break; |
2419 | } |
2420 | |
2421 | return skb; |
2422 | } |
2423 | |
2424 | int rtl_send_smps_action(struct ieee80211_hw *hw, |
2425 | struct ieee80211_sta *sta, |
2426 | enum ieee80211_smps_mode smps) |
2427 | { |
2428 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
2429 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
2430 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
2431 | struct sk_buff *skb = NULL; |
2432 | struct rtl_tcb_desc tcb_desc; |
2433 | u8 bssid[ETH_ALEN] = {0}; |
2434 | |
2435 | memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); |
2436 | |
2437 | if (rtlpriv->mac80211.act_scanning) |
2438 | goto err_free; |
2439 | |
2440 | if (!sta) |
2441 | goto err_free; |
2442 | |
2443 | if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) |
2444 | goto err_free; |
2445 | |
2446 | if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) |
2447 | goto err_free; |
2448 | |
2449 | if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) |
2450 | memcpy(bssid, rtlpriv->efuse.dev_addr, ETH_ALEN); |
2451 | else |
2452 | memcpy(bssid, rtlpriv->mac80211.bssid, ETH_ALEN); |
2453 | |
2454 | skb = rtl_make_smps_action(hw, smps, da: sta->addr, bssid); |
2455 | /* this is a type = mgmt * stype = action frame */ |
2456 | if (skb) { |
2457 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2458 | struct rtl_sta_info *sta_entry = |
2459 | (struct rtl_sta_info *) sta->drv_priv; |
2460 | sta_entry->mimo_ps = smps; |
2461 | /* rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0, true); */ |
2462 | |
2463 | info->control.rates[0].idx = 0; |
2464 | info->band = hw->conf.chandef.chan->band; |
2465 | rtlpriv->intf_ops->adapter_tx(hw, sta, skb, &tcb_desc); |
2466 | } |
2467 | return 1; |
2468 | |
2469 | err_free: |
2470 | return 0; |
2471 | } |
2472 | EXPORT_SYMBOL(rtl_send_smps_action); |
2473 | |
2474 | void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) |
2475 | { |
2476 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
2477 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
2478 | enum io_type iotype; |
2479 | |
2480 | if (!is_hal_stop(rtlhal)) { |
2481 | switch (operation) { |
2482 | case SCAN_OPT_BACKUP: |
2483 | iotype = IO_CMD_PAUSE_DM_BY_SCAN; |
2484 | rtlpriv->cfg->ops->set_hw_reg(hw, |
2485 | HW_VAR_IO_CMD, |
2486 | (u8 *)&iotype); |
2487 | break; |
2488 | case SCAN_OPT_RESTORE: |
2489 | iotype = IO_CMD_RESUME_DM_BY_SCAN; |
2490 | rtlpriv->cfg->ops->set_hw_reg(hw, |
2491 | HW_VAR_IO_CMD, |
2492 | (u8 *)&iotype); |
2493 | break; |
2494 | default: |
2495 | pr_err("Unknown Scan Backup operation.\n" ); |
2496 | break; |
2497 | } |
2498 | } |
2499 | } |
2500 | EXPORT_SYMBOL(rtl_phy_scan_operation_backup); |
2501 | |
2502 | /* because mac80211 have issues when can receive del ba |
2503 | * so here we just make a fake del_ba if we receive a ba_req |
2504 | * but rx_agg was opened to let mac80211 release some ba |
2505 | * related resources, so please this del_ba for tx |
2506 | */ |
2507 | struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, |
2508 | u8 *sa, u8 *bssid, u16 tid) |
2509 | { |
2510 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
2511 | struct sk_buff *skb; |
2512 | struct ieee80211_mgmt *action_frame; |
2513 | u16 params; |
2514 | |
2515 | /* 27 = header + category + action + smps mode */ |
2516 | skb = dev_alloc_skb(length: 34 + hw->extra_tx_headroom); |
2517 | if (!skb) |
2518 | return NULL; |
2519 | |
2520 | skb_reserve(skb, len: hw->extra_tx_headroom); |
2521 | action_frame = skb_put_zero(skb, len: 34); |
2522 | memcpy(action_frame->sa, sa, ETH_ALEN); |
2523 | memcpy(action_frame->da, rtlefuse->dev_addr, ETH_ALEN); |
2524 | memcpy(action_frame->bssid, bssid, ETH_ALEN); |
2525 | action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
2526 | IEEE80211_STYPE_ACTION); |
2527 | action_frame->u.action.category = WLAN_CATEGORY_BACK; |
2528 | action_frame->u.action.u.delba.action_code = WLAN_ACTION_DELBA; |
2529 | params = (u16)(1 << 11); /* bit 11 initiator */ |
2530 | params |= (u16)(tid << 12); /* bit 15:12 TID number */ |
2531 | |
2532 | action_frame->u.action.u.delba.params = cpu_to_le16(params); |
2533 | action_frame->u.action.u.delba.reason_code = |
2534 | cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); |
2535 | |
2536 | return skb; |
2537 | } |
2538 | |
2539 | /********************************************************* |
2540 | * |
2541 | * IOT functions |
2542 | * |
2543 | *********************************************************/ |
2544 | static bool rtl_chk_vendor_ouisub(struct ieee80211_hw *hw, |
2545 | struct octet_string vendor_ie) |
2546 | { |
2547 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
2548 | bool matched = false; |
2549 | static u8 athcap_1[] = { 0x00, 0x03, 0x7F }; |
2550 | static u8 athcap_2[] = { 0x00, 0x13, 0x74 }; |
2551 | static u8 broadcap_1[] = { 0x00, 0x10, 0x18 }; |
2552 | static u8 broadcap_2[] = { 0x00, 0x0a, 0xf7 }; |
2553 | static u8 broadcap_3[] = { 0x00, 0x05, 0xb5 }; |
2554 | static u8 racap[] = { 0x00, 0x0c, 0x43 }; |
2555 | static u8 ciscocap[] = { 0x00, 0x40, 0x96 }; |
2556 | static u8 marvcap[] = { 0x00, 0x50, 0x43 }; |
2557 | |
2558 | if (memcmp(p: vendor_ie.octet, q: athcap_1, size: 3) == 0 || |
2559 | memcmp(p: vendor_ie.octet, q: athcap_2, size: 3) == 0) { |
2560 | rtlpriv->mac80211.vendor = PEER_ATH; |
2561 | matched = true; |
2562 | } else if (memcmp(p: vendor_ie.octet, q: broadcap_1, size: 3) == 0 || |
2563 | memcmp(p: vendor_ie.octet, q: broadcap_2, size: 3) == 0 || |
2564 | memcmp(p: vendor_ie.octet, q: broadcap_3, size: 3) == 0) { |
2565 | rtlpriv->mac80211.vendor = PEER_BROAD; |
2566 | matched = true; |
2567 | } else if (memcmp(p: vendor_ie.octet, q: racap, size: 3) == 0) { |
2568 | rtlpriv->mac80211.vendor = PEER_RAL; |
2569 | matched = true; |
2570 | } else if (memcmp(p: vendor_ie.octet, q: ciscocap, size: 3) == 0) { |
2571 | rtlpriv->mac80211.vendor = PEER_CISCO; |
2572 | matched = true; |
2573 | } else if (memcmp(p: vendor_ie.octet, q: marvcap, size: 3) == 0) { |
2574 | rtlpriv->mac80211.vendor = PEER_MARV; |
2575 | matched = true; |
2576 | } |
2577 | |
2578 | return matched; |
2579 | } |
2580 | |
2581 | static bool rtl_find_221_ie(struct ieee80211_hw *hw, u8 *data, |
2582 | unsigned int len) |
2583 | { |
2584 | struct ieee80211_mgmt *mgmt = (void *)data; |
2585 | struct octet_string vendor_ie; |
2586 | u8 *pos, *end; |
2587 | |
2588 | pos = (u8 *)mgmt->u.beacon.variable; |
2589 | end = data + len; |
2590 | while (pos < end) { |
2591 | if (pos[0] == 221) { |
2592 | vendor_ie.length = pos[1]; |
2593 | vendor_ie.octet = &pos[2]; |
2594 | if (rtl_chk_vendor_ouisub(hw, vendor_ie)) |
2595 | return true; |
2596 | } |
2597 | |
2598 | if (pos + 2 + pos[1] > end) |
2599 | return false; |
2600 | |
2601 | pos += 2 + pos[1]; |
2602 | } |
2603 | return false; |
2604 | } |
2605 | |
2606 | void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len) |
2607 | { |
2608 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
2609 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
2610 | struct ieee80211_hdr *hdr = (void *)data; |
2611 | u32 vendor = PEER_UNKNOWN; |
2612 | |
2613 | static u8 ap3_1[3] = { 0x00, 0x14, 0xbf }; |
2614 | static u8 ap3_2[3] = { 0x00, 0x1a, 0x70 }; |
2615 | static u8 ap3_3[3] = { 0x00, 0x1d, 0x7e }; |
2616 | static u8 ap4_1[3] = { 0x00, 0x90, 0xcc }; |
2617 | static u8 ap4_2[3] = { 0x00, 0x0e, 0x2e }; |
2618 | static u8 ap4_3[3] = { 0x00, 0x18, 0x02 }; |
2619 | static u8 ap4_4[3] = { 0x00, 0x17, 0x3f }; |
2620 | static u8 ap4_5[3] = { 0x00, 0x1c, 0xdf }; |
2621 | static u8 ap5_1[3] = { 0x00, 0x1c, 0xf0 }; |
2622 | static u8 ap5_2[3] = { 0x00, 0x21, 0x91 }; |
2623 | static u8 ap5_3[3] = { 0x00, 0x24, 0x01 }; |
2624 | static u8 ap5_4[3] = { 0x00, 0x15, 0xe9 }; |
2625 | static u8 ap5_5[3] = { 0x00, 0x17, 0x9A }; |
2626 | static u8 ap5_6[3] = { 0x00, 0x18, 0xE7 }; |
2627 | static u8 ap6_1[3] = { 0x00, 0x17, 0x94 }; |
2628 | static u8 ap7_1[3] = { 0x00, 0x14, 0xa4 }; |
2629 | |
2630 | if (mac->opmode != NL80211_IFTYPE_STATION) |
2631 | return; |
2632 | |
2633 | if (mac->link_state == MAC80211_NOLINK) { |
2634 | mac->vendor = PEER_UNKNOWN; |
2635 | return; |
2636 | } |
2637 | |
2638 | if (mac->cnt_after_linked > 2) |
2639 | return; |
2640 | |
2641 | /* check if this really is a beacon */ |
2642 | if (!ieee80211_is_beacon(fc: hdr->frame_control)) |
2643 | return; |
2644 | |
2645 | /* min. beacon length + FCS_LEN */ |
2646 | if (len <= 40 + FCS_LEN) |
2647 | return; |
2648 | |
2649 | /* and only beacons from the associated BSSID, please */ |
2650 | if (!ether_addr_equal_64bits(addr1: hdr->addr3, addr2: rtlpriv->mac80211.bssid)) |
2651 | return; |
2652 | |
2653 | if (rtl_find_221_ie(hw, data, len)) |
2654 | vendor = mac->vendor; |
2655 | |
2656 | if ((memcmp(p: mac->bssid, q: ap5_1, size: 3) == 0) || |
2657 | (memcmp(p: mac->bssid, q: ap5_2, size: 3) == 0) || |
2658 | (memcmp(p: mac->bssid, q: ap5_3, size: 3) == 0) || |
2659 | (memcmp(p: mac->bssid, q: ap5_4, size: 3) == 0) || |
2660 | (memcmp(p: mac->bssid, q: ap5_5, size: 3) == 0) || |
2661 | (memcmp(p: mac->bssid, q: ap5_6, size: 3) == 0) || |
2662 | vendor == PEER_ATH) { |
2663 | vendor = PEER_ATH; |
2664 | rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>ath find\n" ); |
2665 | } else if ((memcmp(p: mac->bssid, q: ap4_4, size: 3) == 0) || |
2666 | (memcmp(p: mac->bssid, q: ap4_5, size: 3) == 0) || |
2667 | (memcmp(p: mac->bssid, q: ap4_1, size: 3) == 0) || |
2668 | (memcmp(p: mac->bssid, q: ap4_2, size: 3) == 0) || |
2669 | (memcmp(p: mac->bssid, q: ap4_3, size: 3) == 0) || |
2670 | vendor == PEER_RAL) { |
2671 | rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>ral find\n" ); |
2672 | vendor = PEER_RAL; |
2673 | } else if (memcmp(p: mac->bssid, q: ap6_1, size: 3) == 0 || |
2674 | vendor == PEER_CISCO) { |
2675 | vendor = PEER_CISCO; |
2676 | rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>cisco find\n" ); |
2677 | } else if ((memcmp(p: mac->bssid, q: ap3_1, size: 3) == 0) || |
2678 | (memcmp(p: mac->bssid, q: ap3_2, size: 3) == 0) || |
2679 | (memcmp(p: mac->bssid, q: ap3_3, size: 3) == 0) || |
2680 | vendor == PEER_BROAD) { |
2681 | rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>broad find\n" ); |
2682 | vendor = PEER_BROAD; |
2683 | } else if (memcmp(p: mac->bssid, q: ap7_1, size: 3) == 0 || |
2684 | vendor == PEER_MARV) { |
2685 | vendor = PEER_MARV; |
2686 | rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>marv find\n" ); |
2687 | } |
2688 | |
2689 | mac->vendor = vendor; |
2690 | } |
2691 | EXPORT_SYMBOL_GPL(rtl_recognize_peer); |
2692 | |
2693 | MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>" ); |
2694 | MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>" ); |
2695 | MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>" ); |
2696 | MODULE_LICENSE("GPL" ); |
2697 | MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core" ); |
2698 | |
2699 | struct rtl_global_var rtl_global_var = {}; |
2700 | EXPORT_SYMBOL_GPL(rtl_global_var); |
2701 | |
2702 | static int __init rtl_core_module_init(void) |
2703 | { |
2704 | BUILD_BUG_ON(TX_PWR_BY_RATE_NUM_RATE < TX_PWR_BY_RATE_NUM_SECTION); |
2705 | BUILD_BUG_ON(MAX_RATE_SECTION_NUM != MAX_RATE_SECTION); |
2706 | BUILD_BUG_ON(MAX_BASE_NUM_IN_PHY_REG_PG_24G != MAX_RATE_SECTION); |
2707 | BUILD_BUG_ON(MAX_BASE_NUM_IN_PHY_REG_PG_5G != (MAX_RATE_SECTION - 1)); |
2708 | |
2709 | if (rtl_rate_control_register()) |
2710 | pr_err("rtl: Unable to register rtl_rc, use default RC !!\n" ); |
2711 | |
2712 | /* add debugfs */ |
2713 | rtl_debugfs_add_topdir(); |
2714 | |
2715 | /* init some global vars */ |
2716 | INIT_LIST_HEAD(list: &rtl_global_var.glb_priv_list); |
2717 | spin_lock_init(&rtl_global_var.glb_list_lock); |
2718 | |
2719 | return 0; |
2720 | } |
2721 | |
2722 | static void __exit rtl_core_module_exit(void) |
2723 | { |
2724 | /*RC*/ |
2725 | rtl_rate_control_unregister(); |
2726 | |
2727 | /* remove debugfs */ |
2728 | rtl_debugfs_remove_topdir(); |
2729 | } |
2730 | |
2731 | module_init(rtl_core_module_init); |
2732 | module_exit(rtl_core_module_exit); |
2733 | |