18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright(c) 2009-2012 Realtek Corporation.*/ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include "wifi.h" 58c2ecf20Sopenharmony_ci#include "rc.h" 68c2ecf20Sopenharmony_ci#include "base.h" 78c2ecf20Sopenharmony_ci#include "efuse.h" 88c2ecf20Sopenharmony_ci#include "cam.h" 98c2ecf20Sopenharmony_ci#include "ps.h" 108c2ecf20Sopenharmony_ci#include "regd.h" 118c2ecf20Sopenharmony_ci#include "pci.h" 128c2ecf20Sopenharmony_ci#include <linux/ip.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/udp.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* 178c2ecf20Sopenharmony_ci *NOTICE!!!: This file will be very big, we should 188c2ecf20Sopenharmony_ci *keep it clear under following roles: 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci *This file include following parts, so, if you add new 218c2ecf20Sopenharmony_ci *functions into this file, please check which part it 228c2ecf20Sopenharmony_ci *should includes. or check if you should add new part 238c2ecf20Sopenharmony_ci *for this file: 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci *1) mac80211 init functions 268c2ecf20Sopenharmony_ci *2) tx information functions 278c2ecf20Sopenharmony_ci *3) functions called by core.c 288c2ecf20Sopenharmony_ci *4) wq & timer callback functions 298c2ecf20Sopenharmony_ci *5) frame process functions 308c2ecf20Sopenharmony_ci *6) IOT functions 318c2ecf20Sopenharmony_ci *7) sysfs functions 328c2ecf20Sopenharmony_ci *8) vif functions 338c2ecf20Sopenharmony_ci *9) ... 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci/********************************************************* 378c2ecf20Sopenharmony_ci * 388c2ecf20Sopenharmony_ci * mac80211 init functions 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci *********************************************************/ 418c2ecf20Sopenharmony_cistatic struct ieee80211_channel rtl_channeltable_2g[] = { 428c2ecf20Sopenharmony_ci {.center_freq = 2412, .hw_value = 1,}, 438c2ecf20Sopenharmony_ci {.center_freq = 2417, .hw_value = 2,}, 448c2ecf20Sopenharmony_ci {.center_freq = 2422, .hw_value = 3,}, 458c2ecf20Sopenharmony_ci {.center_freq = 2427, .hw_value = 4,}, 468c2ecf20Sopenharmony_ci {.center_freq = 2432, .hw_value = 5,}, 478c2ecf20Sopenharmony_ci {.center_freq = 2437, .hw_value = 6,}, 488c2ecf20Sopenharmony_ci {.center_freq = 2442, .hw_value = 7,}, 498c2ecf20Sopenharmony_ci {.center_freq = 2447, .hw_value = 8,}, 508c2ecf20Sopenharmony_ci {.center_freq = 2452, .hw_value = 9,}, 518c2ecf20Sopenharmony_ci {.center_freq = 2457, .hw_value = 10,}, 528c2ecf20Sopenharmony_ci {.center_freq = 2462, .hw_value = 11,}, 538c2ecf20Sopenharmony_ci {.center_freq = 2467, .hw_value = 12,}, 548c2ecf20Sopenharmony_ci {.center_freq = 2472, .hw_value = 13,}, 558c2ecf20Sopenharmony_ci {.center_freq = 2484, .hw_value = 14,}, 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic struct ieee80211_channel rtl_channeltable_5g[] = { 598c2ecf20Sopenharmony_ci {.center_freq = 5180, .hw_value = 36,}, 608c2ecf20Sopenharmony_ci {.center_freq = 5200, .hw_value = 40,}, 618c2ecf20Sopenharmony_ci {.center_freq = 5220, .hw_value = 44,}, 628c2ecf20Sopenharmony_ci {.center_freq = 5240, .hw_value = 48,}, 638c2ecf20Sopenharmony_ci {.center_freq = 5260, .hw_value = 52,}, 648c2ecf20Sopenharmony_ci {.center_freq = 5280, .hw_value = 56,}, 658c2ecf20Sopenharmony_ci {.center_freq = 5300, .hw_value = 60,}, 668c2ecf20Sopenharmony_ci {.center_freq = 5320, .hw_value = 64,}, 678c2ecf20Sopenharmony_ci {.center_freq = 5500, .hw_value = 100,}, 688c2ecf20Sopenharmony_ci {.center_freq = 5520, .hw_value = 104,}, 698c2ecf20Sopenharmony_ci {.center_freq = 5540, .hw_value = 108,}, 708c2ecf20Sopenharmony_ci {.center_freq = 5560, .hw_value = 112,}, 718c2ecf20Sopenharmony_ci {.center_freq = 5580, .hw_value = 116,}, 728c2ecf20Sopenharmony_ci {.center_freq = 5600, .hw_value = 120,}, 738c2ecf20Sopenharmony_ci {.center_freq = 5620, .hw_value = 124,}, 748c2ecf20Sopenharmony_ci {.center_freq = 5640, .hw_value = 128,}, 758c2ecf20Sopenharmony_ci {.center_freq = 5660, .hw_value = 132,}, 768c2ecf20Sopenharmony_ci {.center_freq = 5680, .hw_value = 136,}, 778c2ecf20Sopenharmony_ci {.center_freq = 5700, .hw_value = 140,}, 788c2ecf20Sopenharmony_ci {.center_freq = 5745, .hw_value = 149,}, 798c2ecf20Sopenharmony_ci {.center_freq = 5765, .hw_value = 153,}, 808c2ecf20Sopenharmony_ci {.center_freq = 5785, .hw_value = 157,}, 818c2ecf20Sopenharmony_ci {.center_freq = 5805, .hw_value = 161,}, 828c2ecf20Sopenharmony_ci {.center_freq = 5825, .hw_value = 165,}, 838c2ecf20Sopenharmony_ci}; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic struct ieee80211_rate rtl_ratetable_2g[] = { 868c2ecf20Sopenharmony_ci {.bitrate = 10, .hw_value = 0x00,}, 878c2ecf20Sopenharmony_ci {.bitrate = 20, .hw_value = 0x01,}, 888c2ecf20Sopenharmony_ci {.bitrate = 55, .hw_value = 0x02,}, 898c2ecf20Sopenharmony_ci {.bitrate = 110, .hw_value = 0x03,}, 908c2ecf20Sopenharmony_ci {.bitrate = 60, .hw_value = 0x04,}, 918c2ecf20Sopenharmony_ci {.bitrate = 90, .hw_value = 0x05,}, 928c2ecf20Sopenharmony_ci {.bitrate = 120, .hw_value = 0x06,}, 938c2ecf20Sopenharmony_ci {.bitrate = 180, .hw_value = 0x07,}, 948c2ecf20Sopenharmony_ci {.bitrate = 240, .hw_value = 0x08,}, 958c2ecf20Sopenharmony_ci {.bitrate = 360, .hw_value = 0x09,}, 968c2ecf20Sopenharmony_ci {.bitrate = 480, .hw_value = 0x0a,}, 978c2ecf20Sopenharmony_ci {.bitrate = 540, .hw_value = 0x0b,}, 988c2ecf20Sopenharmony_ci}; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic struct ieee80211_rate rtl_ratetable_5g[] = { 1018c2ecf20Sopenharmony_ci {.bitrate = 60, .hw_value = 0x04,}, 1028c2ecf20Sopenharmony_ci {.bitrate = 90, .hw_value = 0x05,}, 1038c2ecf20Sopenharmony_ci {.bitrate = 120, .hw_value = 0x06,}, 1048c2ecf20Sopenharmony_ci {.bitrate = 180, .hw_value = 0x07,}, 1058c2ecf20Sopenharmony_ci {.bitrate = 240, .hw_value = 0x08,}, 1068c2ecf20Sopenharmony_ci {.bitrate = 360, .hw_value = 0x09,}, 1078c2ecf20Sopenharmony_ci {.bitrate = 480, .hw_value = 0x0a,}, 1088c2ecf20Sopenharmony_ci {.bitrate = 540, .hw_value = 0x0b,}, 1098c2ecf20Sopenharmony_ci}; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic const struct ieee80211_supported_band rtl_band_2ghz = { 1128c2ecf20Sopenharmony_ci .band = NL80211_BAND_2GHZ, 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci .channels = rtl_channeltable_2g, 1158c2ecf20Sopenharmony_ci .n_channels = ARRAY_SIZE(rtl_channeltable_2g), 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci .bitrates = rtl_ratetable_2g, 1188c2ecf20Sopenharmony_ci .n_bitrates = ARRAY_SIZE(rtl_ratetable_2g), 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci .ht_cap = {0}, 1218c2ecf20Sopenharmony_ci}; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic struct ieee80211_supported_band rtl_band_5ghz = { 1248c2ecf20Sopenharmony_ci .band = NL80211_BAND_5GHZ, 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci .channels = rtl_channeltable_5g, 1278c2ecf20Sopenharmony_ci .n_channels = ARRAY_SIZE(rtl_channeltable_5g), 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci .bitrates = rtl_ratetable_5g, 1308c2ecf20Sopenharmony_ci .n_bitrates = ARRAY_SIZE(rtl_ratetable_5g), 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci .ht_cap = {0}, 1338c2ecf20Sopenharmony_ci}; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic const u8 tid_to_ac[] = { 1368c2ecf20Sopenharmony_ci 2, /* IEEE80211_AC_BE */ 1378c2ecf20Sopenharmony_ci 3, /* IEEE80211_AC_BK */ 1388c2ecf20Sopenharmony_ci 3, /* IEEE80211_AC_BK */ 1398c2ecf20Sopenharmony_ci 2, /* IEEE80211_AC_BE */ 1408c2ecf20Sopenharmony_ci 1, /* IEEE80211_AC_VI */ 1418c2ecf20Sopenharmony_ci 1, /* IEEE80211_AC_VI */ 1428c2ecf20Sopenharmony_ci 0, /* IEEE80211_AC_VO */ 1438c2ecf20Sopenharmony_ci 0, /* IEEE80211_AC_VO */ 1448c2ecf20Sopenharmony_ci}; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ciu8 rtl_tid_to_ac(u8 tid) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci return tid_to_ac[tid]; 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_tid_to_ac); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, 1538c2ecf20Sopenharmony_ci struct ieee80211_sta_ht_cap *ht_cap) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 1568c2ecf20Sopenharmony_ci struct rtl_phy *rtlphy = &(rtlpriv->phy); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci ht_cap->ht_supported = true; 1598c2ecf20Sopenharmony_ci ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 1608c2ecf20Sopenharmony_ci IEEE80211_HT_CAP_SGI_40 | 1618c2ecf20Sopenharmony_ci IEEE80211_HT_CAP_SGI_20 | 1628c2ecf20Sopenharmony_ci IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci if (rtlpriv->rtlhal.disable_amsdu_8k) 1658c2ecf20Sopenharmony_ci ht_cap->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci /* 1688c2ecf20Sopenharmony_ci *Maximum length of AMPDU that the STA can receive. 1698c2ecf20Sopenharmony_ci *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) 1708c2ecf20Sopenharmony_ci */ 1718c2ecf20Sopenharmony_ci ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci /*Minimum MPDU start spacing , */ 1748c2ecf20Sopenharmony_ci ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci /*hw->wiphy->bands[NL80211_BAND_2GHZ] 1798c2ecf20Sopenharmony_ci *base on ant_num 1808c2ecf20Sopenharmony_ci *rx_mask: RX mask 1818c2ecf20Sopenharmony_ci *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7 1828c2ecf20Sopenharmony_ci *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15 1838c2ecf20Sopenharmony_ci *if rx_ant >= 3 rx_mask[2]= 0xff; 1848c2ecf20Sopenharmony_ci *if BW_40 rx_mask[4]= 0x01; 1858c2ecf20Sopenharmony_ci *highest supported RX rate 1868c2ecf20Sopenharmony_ci */ 1878c2ecf20Sopenharmony_ci if (rtlpriv->dm.supp_phymode_switch) { 1888c2ecf20Sopenharmony_ci pr_info("Support phy mode switch\n"); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[0] = 0xFF; 1918c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[1] = 0xFF; 1928c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[4] = 0x01; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); 1958c2ecf20Sopenharmony_ci } else { 1968c2ecf20Sopenharmony_ci if (get_rf_type(rtlphy) == RF_1T2R || 1978c2ecf20Sopenharmony_ci get_rf_type(rtlphy) == RF_2T2R) { 1988c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, 1998c2ecf20Sopenharmony_ci "1T2R or 2T2R\n"); 2008c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[0] = 0xFF; 2018c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[1] = 0xFF; 2028c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[4] = 0x01; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci ht_cap->mcs.rx_highest = 2058c2ecf20Sopenharmony_ci cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); 2068c2ecf20Sopenharmony_ci } else if (get_rf_type(rtlphy) == RF_1T1R) { 2078c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n"); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[0] = 0xFF; 2108c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[1] = 0x00; 2118c2ecf20Sopenharmony_ci ht_cap->mcs.rx_mask[4] = 0x01; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci ht_cap->mcs.rx_highest = 2148c2ecf20Sopenharmony_ci cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7); 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci } 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic void _rtl_init_hw_vht_capab(struct ieee80211_hw *hw, 2208c2ecf20Sopenharmony_ci struct ieee80211_sta_vht_cap *vht_cap) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 2238c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtlpriv); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci if (!(rtlpriv->cfg->spec_ver & RTL_SPEC_SUPPORT_VHT)) 2268c2ecf20Sopenharmony_ci return; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE || 2298c2ecf20Sopenharmony_ci rtlhal->hw_type == HARDWARE_TYPE_RTL8822BE) { 2308c2ecf20Sopenharmony_ci u16 mcs_map; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci vht_cap->vht_supported = true; 2338c2ecf20Sopenharmony_ci vht_cap->cap = 2348c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | 2358c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_SHORT_GI_80 | 2368c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_TXSTBC | 2378c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_RXSTBC_1 | 2388c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | 2398c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | 2408c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_HTC_VHT | 2418c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | 2428c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | 2438c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | 2448c2ecf20Sopenharmony_ci 0; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | 2478c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 | 2488c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | 2498c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | 2508c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | 2518c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | 2528c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | 2538c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); 2568c2ecf20Sopenharmony_ci vht_cap->vht_mcs.rx_highest = 2578c2ecf20Sopenharmony_ci cpu_to_le16(MAX_BIT_RATE_SHORT_GI_2NSS_80MHZ_MCS9); 2588c2ecf20Sopenharmony_ci vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); 2598c2ecf20Sopenharmony_ci vht_cap->vht_mcs.tx_highest = 2608c2ecf20Sopenharmony_ci cpu_to_le16(MAX_BIT_RATE_SHORT_GI_2NSS_80MHZ_MCS9); 2618c2ecf20Sopenharmony_ci } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { 2628c2ecf20Sopenharmony_ci u16 mcs_map; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci vht_cap->vht_supported = true; 2658c2ecf20Sopenharmony_ci vht_cap->cap = 2668c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | 2678c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_SHORT_GI_80 | 2688c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_TXSTBC | 2698c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_RXSTBC_1 | 2708c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | 2718c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | 2728c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_HTC_VHT | 2738c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | 2748c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | 2758c2ecf20Sopenharmony_ci IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | 2768c2ecf20Sopenharmony_ci 0; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | 2798c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 | 2808c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | 2818c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | 2828c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | 2838c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | 2848c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | 2858c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); 2888c2ecf20Sopenharmony_ci vht_cap->vht_mcs.rx_highest = 2898c2ecf20Sopenharmony_ci cpu_to_le16(MAX_BIT_RATE_SHORT_GI_1NSS_80MHZ_MCS9); 2908c2ecf20Sopenharmony_ci vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); 2918c2ecf20Sopenharmony_ci vht_cap->vht_mcs.tx_highest = 2928c2ecf20Sopenharmony_ci cpu_to_le16(MAX_BIT_RATE_SHORT_GI_1NSS_80MHZ_MCS9); 2938c2ecf20Sopenharmony_ci } 2948c2ecf20Sopenharmony_ci} 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_cistatic void _rtl_init_mac80211(struct ieee80211_hw *hw) 2978c2ecf20Sopenharmony_ci{ 2988c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 2998c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtlpriv); 3008c2ecf20Sopenharmony_ci struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); 3018c2ecf20Sopenharmony_ci struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 3028c2ecf20Sopenharmony_ci struct ieee80211_supported_band *sband; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && 3058c2ecf20Sopenharmony_ci rtlhal->bandset == BAND_ON_BOTH) { 3068c2ecf20Sopenharmony_ci /* 1: 2.4 G bands */ 3078c2ecf20Sopenharmony_ci /* <1> use mac->bands as mem for hw->wiphy->bands */ 3088c2ecf20Sopenharmony_ci sband = &(rtlmac->bands[NL80211_BAND_2GHZ]); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci /* <2> set hw->wiphy->bands[NL80211_BAND_2GHZ] 3118c2ecf20Sopenharmony_ci * to default value(1T1R) */ 3128c2ecf20Sopenharmony_ci memcpy(&(rtlmac->bands[NL80211_BAND_2GHZ]), &rtl_band_2ghz, 3138c2ecf20Sopenharmony_ci sizeof(struct ieee80211_supported_band)); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci /* <3> init ht cap base on ant_num */ 3168c2ecf20Sopenharmony_ci _rtl_init_hw_ht_capab(hw, &sband->ht_cap); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci /* <4> set mac->sband to wiphy->sband */ 3198c2ecf20Sopenharmony_ci hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* 2: 5 G bands */ 3228c2ecf20Sopenharmony_ci /* <1> use mac->bands as mem for hw->wiphy->bands */ 3238c2ecf20Sopenharmony_ci sband = &(rtlmac->bands[NL80211_BAND_5GHZ]); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci /* <2> set hw->wiphy->bands[NL80211_BAND_5GHZ] 3268c2ecf20Sopenharmony_ci * to default value(1T1R) */ 3278c2ecf20Sopenharmony_ci memcpy(&(rtlmac->bands[NL80211_BAND_5GHZ]), &rtl_band_5ghz, 3288c2ecf20Sopenharmony_ci sizeof(struct ieee80211_supported_band)); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci /* <3> init ht cap base on ant_num */ 3318c2ecf20Sopenharmony_ci _rtl_init_hw_ht_capab(hw, &sband->ht_cap); 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci _rtl_init_hw_vht_capab(hw, &sband->vht_cap); 3348c2ecf20Sopenharmony_ci /* <4> set mac->sband to wiphy->sband */ 3358c2ecf20Sopenharmony_ci hw->wiphy->bands[NL80211_BAND_5GHZ] = sband; 3368c2ecf20Sopenharmony_ci } else { 3378c2ecf20Sopenharmony_ci if (rtlhal->current_bandtype == BAND_ON_2_4G) { 3388c2ecf20Sopenharmony_ci /* <1> use mac->bands as mem for hw->wiphy->bands */ 3398c2ecf20Sopenharmony_ci sband = &(rtlmac->bands[NL80211_BAND_2GHZ]); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci /* <2> set hw->wiphy->bands[NL80211_BAND_2GHZ] 3428c2ecf20Sopenharmony_ci * to default value(1T1R) */ 3438c2ecf20Sopenharmony_ci memcpy(&(rtlmac->bands[NL80211_BAND_2GHZ]), 3448c2ecf20Sopenharmony_ci &rtl_band_2ghz, 3458c2ecf20Sopenharmony_ci sizeof(struct ieee80211_supported_band)); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci /* <3> init ht cap base on ant_num */ 3488c2ecf20Sopenharmony_ci _rtl_init_hw_ht_capab(hw, &sband->ht_cap); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci /* <4> set mac->sband to wiphy->sband */ 3518c2ecf20Sopenharmony_ci hw->wiphy->bands[NL80211_BAND_2GHZ] = sband; 3528c2ecf20Sopenharmony_ci } else if (rtlhal->current_bandtype == BAND_ON_5G) { 3538c2ecf20Sopenharmony_ci /* <1> use mac->bands as mem for hw->wiphy->bands */ 3548c2ecf20Sopenharmony_ci sband = &(rtlmac->bands[NL80211_BAND_5GHZ]); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci /* <2> set hw->wiphy->bands[NL80211_BAND_5GHZ] 3578c2ecf20Sopenharmony_ci * to default value(1T1R) */ 3588c2ecf20Sopenharmony_ci memcpy(&(rtlmac->bands[NL80211_BAND_5GHZ]), 3598c2ecf20Sopenharmony_ci &rtl_band_5ghz, 3608c2ecf20Sopenharmony_ci sizeof(struct ieee80211_supported_band)); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci /* <3> init ht cap base on ant_num */ 3638c2ecf20Sopenharmony_ci _rtl_init_hw_ht_capab(hw, &sband->ht_cap); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci _rtl_init_hw_vht_capab(hw, &sband->vht_cap); 3668c2ecf20Sopenharmony_ci /* <4> set mac->sband to wiphy->sband */ 3678c2ecf20Sopenharmony_ci hw->wiphy->bands[NL80211_BAND_5GHZ] = sband; 3688c2ecf20Sopenharmony_ci } else { 3698c2ecf20Sopenharmony_ci pr_err("Err BAND %d\n", 3708c2ecf20Sopenharmony_ci rtlhal->current_bandtype); 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci /* <5> set hw caps */ 3748c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, SIGNAL_DBM); 3758c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, RX_INCLUDES_FCS); 3768c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, AMPDU_AGGREGATION); 3778c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, MFP_CAPABLE); 3788c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); 3798c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); 3808c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci /* swlps or hwlps has been set in diff chip in init_sw_vars */ 3838c2ecf20Sopenharmony_ci if (rtlpriv->psc.swctrl_lps) { 3848c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, SUPPORTS_PS); 3858c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, PS_NULLFUNC_STACK); 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci if (rtlpriv->psc.fwctrl_lps) { 3888c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, SUPPORTS_PS); 3898c2ecf20Sopenharmony_ci ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); 3908c2ecf20Sopenharmony_ci } 3918c2ecf20Sopenharmony_ci hw->wiphy->interface_modes = 3928c2ecf20Sopenharmony_ci BIT(NL80211_IFTYPE_AP) | 3938c2ecf20Sopenharmony_ci BIT(NL80211_IFTYPE_STATION) | 3948c2ecf20Sopenharmony_ci BIT(NL80211_IFTYPE_ADHOC) | 3958c2ecf20Sopenharmony_ci BIT(NL80211_IFTYPE_MESH_POINT) | 3968c2ecf20Sopenharmony_ci BIT(NL80211_IFTYPE_P2P_CLIENT) | 3978c2ecf20Sopenharmony_ci BIT(NL80211_IFTYPE_P2P_GO); 3988c2ecf20Sopenharmony_ci hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci hw->wiphy->rts_threshold = 2347; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci hw->queues = AC_MAX; 4058c2ecf20Sopenharmony_ci hw->extra_tx_headroom = RTL_TX_HEADER_SIZE; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci /* TODO: Correct this value for our hw */ 4088c2ecf20Sopenharmony_ci hw->max_listen_interval = MAX_LISTEN_INTERVAL; 4098c2ecf20Sopenharmony_ci hw->max_rate_tries = MAX_RATE_TRIES; 4108c2ecf20Sopenharmony_ci /* hw->max_rates = 1; */ 4118c2ecf20Sopenharmony_ci hw->sta_data_size = sizeof(struct rtl_sta_info); 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci/* wowlan is not supported by kernel if CONFIG_PM is not defined */ 4148c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 4158c2ecf20Sopenharmony_ci if (rtlpriv->psc.wo_wlan_mode) { 4168c2ecf20Sopenharmony_ci if (rtlpriv->psc.wo_wlan_mode & WAKE_ON_MAGIC_PACKET) 4178c2ecf20Sopenharmony_ci rtlpriv->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT; 4188c2ecf20Sopenharmony_ci if (rtlpriv->psc.wo_wlan_mode & WAKE_ON_PATTERN_MATCH) { 4198c2ecf20Sopenharmony_ci rtlpriv->wowlan.n_patterns = 4208c2ecf20Sopenharmony_ci MAX_SUPPORT_WOL_PATTERN_NUM; 4218c2ecf20Sopenharmony_ci rtlpriv->wowlan.pattern_min_len = MIN_WOL_PATTERN_SIZE; 4228c2ecf20Sopenharmony_ci rtlpriv->wowlan.pattern_max_len = MAX_WOL_PATTERN_SIZE; 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci hw->wiphy->wowlan = &rtlpriv->wowlan; 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci#endif 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci /* <6> mac address */ 4298c2ecf20Sopenharmony_ci if (is_valid_ether_addr(rtlefuse->dev_addr)) { 4308c2ecf20Sopenharmony_ci SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr); 4318c2ecf20Sopenharmony_ci } else { 4328c2ecf20Sopenharmony_ci u8 rtlmac1[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 }; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci get_random_bytes((rtlmac1 + (ETH_ALEN - 1)), 1); 4358c2ecf20Sopenharmony_ci SET_IEEE80211_PERM_ADDR(hw, rtlmac1); 4368c2ecf20Sopenharmony_ci } 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_cistatic void rtl_watchdog_wq_callback(struct work_struct *work); 4408c2ecf20Sopenharmony_cistatic void rtl_fwevt_wq_callback(struct work_struct *work); 4418c2ecf20Sopenharmony_cistatic void rtl_c2hcmd_wq_callback(struct work_struct *work); 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_cistatic int _rtl_init_deferred_work(struct ieee80211_hw *hw) 4448c2ecf20Sopenharmony_ci{ 4458c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 4468c2ecf20Sopenharmony_ci struct workqueue_struct *wq; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name); 4498c2ecf20Sopenharmony_ci if (!wq) 4508c2ecf20Sopenharmony_ci return -ENOMEM; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci /* <1> timer */ 4538c2ecf20Sopenharmony_ci timer_setup(&rtlpriv->works.watchdog_timer, 4548c2ecf20Sopenharmony_ci rtl_watch_dog_timer_callback, 0); 4558c2ecf20Sopenharmony_ci timer_setup(&rtlpriv->works.dualmac_easyconcurrent_retrytimer, 4568c2ecf20Sopenharmony_ci rtl_easy_concurrent_retrytimer_callback, 0); 4578c2ecf20Sopenharmony_ci /* <2> work queue */ 4588c2ecf20Sopenharmony_ci rtlpriv->works.hw = hw; 4598c2ecf20Sopenharmony_ci rtlpriv->works.rtl_wq = wq; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq, 4628c2ecf20Sopenharmony_ci rtl_watchdog_wq_callback); 4638c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, 4648c2ecf20Sopenharmony_ci rtl_ips_nic_off_wq_callback); 4658c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&rtlpriv->works.ps_work, rtl_swlps_wq_callback); 4668c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq, 4678c2ecf20Sopenharmony_ci rtl_swlps_rfon_wq_callback); 4688c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq, rtl_fwevt_wq_callback); 4698c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&rtlpriv->works.c2hcmd_wq, rtl_c2hcmd_wq_callback); 4708c2ecf20Sopenharmony_ci return 0; 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_civoid rtl_deinit_deferred_work(struct ieee80211_hw *hw, bool ips_wq) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci del_timer_sync(&rtlpriv->works.watchdog_timer); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&rtlpriv->works.watchdog_wq); 4808c2ecf20Sopenharmony_ci if (ips_wq) 4818c2ecf20Sopenharmony_ci cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); 4828c2ecf20Sopenharmony_ci else 4838c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&rtlpriv->works.ips_nic_off_wq); 4848c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&rtlpriv->works.ps_work); 4858c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&rtlpriv->works.ps_rfon_wq); 4868c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&rtlpriv->works.fwevt_wq); 4878c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&rtlpriv->works.c2hcmd_wq); 4888c2ecf20Sopenharmony_ci} 4898c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_deinit_deferred_work); 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_civoid rtl_init_rfkill(struct ieee80211_hw *hw) 4928c2ecf20Sopenharmony_ci{ 4938c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci bool radio_state; 4968c2ecf20Sopenharmony_ci bool blocked; 4978c2ecf20Sopenharmony_ci u8 valid = 0; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci /*set init state to on */ 5008c2ecf20Sopenharmony_ci rtlpriv->rfkill.rfkill_state = true; 5018c2ecf20Sopenharmony_ci wiphy_rfkill_set_hw_state(hw->wiphy, 0); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci if (valid) { 5068c2ecf20Sopenharmony_ci pr_info("rtlwifi: wireless switch is %s\n", 5078c2ecf20Sopenharmony_ci rtlpriv->rfkill.rfkill_state ? "on" : "off"); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci rtlpriv->rfkill.rfkill_state = radio_state; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci blocked = rtlpriv->rfkill.rfkill_state != 1; 5128c2ecf20Sopenharmony_ci wiphy_rfkill_set_hw_state(hw->wiphy, blocked); 5138c2ecf20Sopenharmony_ci } 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci wiphy_rfkill_start_polling(hw->wiphy); 5168c2ecf20Sopenharmony_ci} 5178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_init_rfkill); 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_civoid rtl_deinit_rfkill(struct ieee80211_hw *hw) 5208c2ecf20Sopenharmony_ci{ 5218c2ecf20Sopenharmony_ci wiphy_rfkill_stop_polling(hw->wiphy); 5228c2ecf20Sopenharmony_ci} 5238c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_deinit_rfkill); 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ciint rtl_init_core(struct ieee80211_hw *hw) 5268c2ecf20Sopenharmony_ci{ 5278c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 5288c2ecf20Sopenharmony_ci struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci /* <1> init mac80211 */ 5318c2ecf20Sopenharmony_ci _rtl_init_mac80211(hw); 5328c2ecf20Sopenharmony_ci rtlmac->hw = hw; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci /* <2> rate control register */ 5358c2ecf20Sopenharmony_ci hw->rate_control_algorithm = "rtl_rc"; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci /* 5388c2ecf20Sopenharmony_ci * <3> init CRDA must come after init 5398c2ecf20Sopenharmony_ci * mac80211 hw in _rtl_init_mac80211. 5408c2ecf20Sopenharmony_ci */ 5418c2ecf20Sopenharmony_ci if (rtl_regd_init(hw, rtl_reg_notifier)) { 5428c2ecf20Sopenharmony_ci pr_err("REGD init failed\n"); 5438c2ecf20Sopenharmony_ci return 1; 5448c2ecf20Sopenharmony_ci } 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci /* <4> locks */ 5478c2ecf20Sopenharmony_ci mutex_init(&rtlpriv->locks.conf_mutex); 5488c2ecf20Sopenharmony_ci mutex_init(&rtlpriv->locks.ips_mutex); 5498c2ecf20Sopenharmony_ci mutex_init(&rtlpriv->locks.lps_mutex); 5508c2ecf20Sopenharmony_ci spin_lock_init(&rtlpriv->locks.irq_th_lock); 5518c2ecf20Sopenharmony_ci spin_lock_init(&rtlpriv->locks.h2c_lock); 5528c2ecf20Sopenharmony_ci spin_lock_init(&rtlpriv->locks.rf_ps_lock); 5538c2ecf20Sopenharmony_ci spin_lock_init(&rtlpriv->locks.rf_lock); 5548c2ecf20Sopenharmony_ci spin_lock_init(&rtlpriv->locks.waitq_lock); 5558c2ecf20Sopenharmony_ci spin_lock_init(&rtlpriv->locks.entry_list_lock); 5568c2ecf20Sopenharmony_ci spin_lock_init(&rtlpriv->locks.c2hcmd_lock); 5578c2ecf20Sopenharmony_ci spin_lock_init(&rtlpriv->locks.scan_list_lock); 5588c2ecf20Sopenharmony_ci spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); 5598c2ecf20Sopenharmony_ci spin_lock_init(&rtlpriv->locks.fw_ps_lock); 5608c2ecf20Sopenharmony_ci spin_lock_init(&rtlpriv->locks.iqk_lock); 5618c2ecf20Sopenharmony_ci /* <5> init list */ 5628c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&rtlpriv->entry_list); 5638c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&rtlpriv->scan_list.list); 5648c2ecf20Sopenharmony_ci skb_queue_head_init(&rtlpriv->tx_report.queue); 5658c2ecf20Sopenharmony_ci skb_queue_head_init(&rtlpriv->c2hcmd_queue); 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci rtlmac->link_state = MAC80211_NOLINK; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci /* <6> init deferred work */ 5708c2ecf20Sopenharmony_ci return _rtl_init_deferred_work(hw); 5718c2ecf20Sopenharmony_ci} 5728c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_init_core); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_cistatic void rtl_free_entries_from_scan_list(struct ieee80211_hw *hw); 5758c2ecf20Sopenharmony_cistatic void rtl_free_entries_from_ack_queue(struct ieee80211_hw *hw, 5768c2ecf20Sopenharmony_ci bool timeout); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_civoid rtl_deinit_core(struct ieee80211_hw *hw) 5798c2ecf20Sopenharmony_ci{ 5808c2ecf20Sopenharmony_ci rtl_c2hcmd_launcher(hw, 0); 5818c2ecf20Sopenharmony_ci rtl_free_entries_from_scan_list(hw); 5828c2ecf20Sopenharmony_ci rtl_free_entries_from_ack_queue(hw, false); 5838c2ecf20Sopenharmony_ci} 5848c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_deinit_core); 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_civoid rtl_init_rx_config(struct ieee80211_hw *hw) 5878c2ecf20Sopenharmony_ci{ 5888c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 5898c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); 5928c2ecf20Sopenharmony_ci} 5938c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_init_rx_config); 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci/********************************************************* 5968c2ecf20Sopenharmony_ci * 5978c2ecf20Sopenharmony_ci * tx information functions 5988c2ecf20Sopenharmony_ci * 5998c2ecf20Sopenharmony_ci *********************************************************/ 6008c2ecf20Sopenharmony_cistatic void _rtl_qurey_shortpreamble_mode(struct ieee80211_hw *hw, 6018c2ecf20Sopenharmony_ci struct rtl_tcb_desc *tcb_desc, 6028c2ecf20Sopenharmony_ci struct ieee80211_tx_info *info) 6038c2ecf20Sopenharmony_ci{ 6048c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 6058c2ecf20Sopenharmony_ci u8 rate_flag = info->control.rates[0].flags; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci tcb_desc->use_shortpreamble = false; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci /* 1M can only use Long Preamble. 11B spec */ 6108c2ecf20Sopenharmony_ci if (tcb_desc->hw_rate == rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]) 6118c2ecf20Sopenharmony_ci return; 6128c2ecf20Sopenharmony_ci else if (rate_flag & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) 6138c2ecf20Sopenharmony_ci tcb_desc->use_shortpreamble = true; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci return; 6168c2ecf20Sopenharmony_ci} 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_cistatic void _rtl_query_shortgi(struct ieee80211_hw *hw, 6198c2ecf20Sopenharmony_ci struct ieee80211_sta *sta, 6208c2ecf20Sopenharmony_ci struct rtl_tcb_desc *tcb_desc, 6218c2ecf20Sopenharmony_ci struct ieee80211_tx_info *info) 6228c2ecf20Sopenharmony_ci{ 6238c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 6248c2ecf20Sopenharmony_ci u8 rate_flag = info->control.rates[0].flags; 6258c2ecf20Sopenharmony_ci u8 sgi_40 = 0, sgi_20 = 0, bw_40 = 0; 6268c2ecf20Sopenharmony_ci u8 sgi_80 = 0, bw_80 = 0; 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci tcb_desc->use_shortgi = false; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci if (sta == NULL) 6318c2ecf20Sopenharmony_ci return; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; 6348c2ecf20Sopenharmony_ci sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; 6358c2ecf20Sopenharmony_ci sgi_80 = sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci if ((!sta->ht_cap.ht_supported) && (!sta->vht_cap.vht_supported)) 6388c2ecf20Sopenharmony_ci return; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci if (!sgi_40 && !sgi_20) 6418c2ecf20Sopenharmony_ci return; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci if (mac->opmode == NL80211_IFTYPE_STATION) { 6448c2ecf20Sopenharmony_ci bw_40 = mac->bw_40; 6458c2ecf20Sopenharmony_ci bw_80 = mac->bw_80; 6468c2ecf20Sopenharmony_ci } else if (mac->opmode == NL80211_IFTYPE_AP || 6478c2ecf20Sopenharmony_ci mac->opmode == NL80211_IFTYPE_ADHOC || 6488c2ecf20Sopenharmony_ci mac->opmode == NL80211_IFTYPE_MESH_POINT) { 6498c2ecf20Sopenharmony_ci bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; 6508c2ecf20Sopenharmony_ci bw_80 = sta->vht_cap.vht_supported; 6518c2ecf20Sopenharmony_ci } 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci if (bw_80) { 6548c2ecf20Sopenharmony_ci if (sgi_80) 6558c2ecf20Sopenharmony_ci tcb_desc->use_shortgi = true; 6568c2ecf20Sopenharmony_ci else 6578c2ecf20Sopenharmony_ci tcb_desc->use_shortgi = false; 6588c2ecf20Sopenharmony_ci } else { 6598c2ecf20Sopenharmony_ci if (bw_40 && sgi_40) 6608c2ecf20Sopenharmony_ci tcb_desc->use_shortgi = true; 6618c2ecf20Sopenharmony_ci else if (!bw_40 && sgi_20) 6628c2ecf20Sopenharmony_ci tcb_desc->use_shortgi = true; 6638c2ecf20Sopenharmony_ci } 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci if (!(rate_flag & IEEE80211_TX_RC_SHORT_GI)) 6668c2ecf20Sopenharmony_ci tcb_desc->use_shortgi = false; 6678c2ecf20Sopenharmony_ci} 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_cistatic void _rtl_query_protection_mode(struct ieee80211_hw *hw, 6708c2ecf20Sopenharmony_ci struct rtl_tcb_desc *tcb_desc, 6718c2ecf20Sopenharmony_ci struct ieee80211_tx_info *info) 6728c2ecf20Sopenharmony_ci{ 6738c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 6748c2ecf20Sopenharmony_ci u8 rate_flag = info->control.rates[0].flags; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci /* Common Settings */ 6778c2ecf20Sopenharmony_ci tcb_desc->rts_stbc = false; 6788c2ecf20Sopenharmony_ci tcb_desc->cts_enable = false; 6798c2ecf20Sopenharmony_ci tcb_desc->rts_sc = 0; 6808c2ecf20Sopenharmony_ci tcb_desc->rts_bw = false; 6818c2ecf20Sopenharmony_ci tcb_desc->rts_use_shortpreamble = false; 6828c2ecf20Sopenharmony_ci tcb_desc->rts_use_shortgi = false; 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci if (rate_flag & IEEE80211_TX_RC_USE_CTS_PROTECT) { 6858c2ecf20Sopenharmony_ci /* Use CTS-to-SELF in protection mode. */ 6868c2ecf20Sopenharmony_ci tcb_desc->rts_enable = true; 6878c2ecf20Sopenharmony_ci tcb_desc->cts_enable = true; 6888c2ecf20Sopenharmony_ci tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M]; 6898c2ecf20Sopenharmony_ci } else if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) { 6908c2ecf20Sopenharmony_ci /* Use RTS-CTS in protection mode. */ 6918c2ecf20Sopenharmony_ci tcb_desc->rts_enable = true; 6928c2ecf20Sopenharmony_ci tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M]; 6938c2ecf20Sopenharmony_ci } 6948c2ecf20Sopenharmony_ci} 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ciu8 rtl_mrate_idx_to_arfr_id(struct ieee80211_hw *hw, u8 rate_index, 6978c2ecf20Sopenharmony_ci enum wireless_mode wirelessmode) 6988c2ecf20Sopenharmony_ci{ 6998c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 7008c2ecf20Sopenharmony_ci struct rtl_phy *rtlphy = &rtlpriv->phy; 7018c2ecf20Sopenharmony_ci u8 ret = 0; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci switch (rate_index) { 7048c2ecf20Sopenharmony_ci case RATR_INX_WIRELESS_NGB: 7058c2ecf20Sopenharmony_ci if (rtlphy->rf_type == RF_1T1R) 7068c2ecf20Sopenharmony_ci ret = RATEID_IDX_BGN_40M_1SS; 7078c2ecf20Sopenharmony_ci else 7088c2ecf20Sopenharmony_ci ret = RATEID_IDX_BGN_40M_2SS; 7098c2ecf20Sopenharmony_ci ; break; 7108c2ecf20Sopenharmony_ci case RATR_INX_WIRELESS_N: 7118c2ecf20Sopenharmony_ci case RATR_INX_WIRELESS_NG: 7128c2ecf20Sopenharmony_ci if (rtlphy->rf_type == RF_1T1R) 7138c2ecf20Sopenharmony_ci ret = RATEID_IDX_GN_N1SS; 7148c2ecf20Sopenharmony_ci else 7158c2ecf20Sopenharmony_ci ret = RATEID_IDX_GN_N2SS; 7168c2ecf20Sopenharmony_ci ; break; 7178c2ecf20Sopenharmony_ci case RATR_INX_WIRELESS_NB: 7188c2ecf20Sopenharmony_ci if (rtlphy->rf_type == RF_1T1R) 7198c2ecf20Sopenharmony_ci ret = RATEID_IDX_BGN_20M_1SS_BN; 7208c2ecf20Sopenharmony_ci else 7218c2ecf20Sopenharmony_ci ret = RATEID_IDX_BGN_20M_2SS_BN; 7228c2ecf20Sopenharmony_ci ; break; 7238c2ecf20Sopenharmony_ci case RATR_INX_WIRELESS_GB: 7248c2ecf20Sopenharmony_ci ret = RATEID_IDX_BG; 7258c2ecf20Sopenharmony_ci break; 7268c2ecf20Sopenharmony_ci case RATR_INX_WIRELESS_G: 7278c2ecf20Sopenharmony_ci ret = RATEID_IDX_G; 7288c2ecf20Sopenharmony_ci break; 7298c2ecf20Sopenharmony_ci case RATR_INX_WIRELESS_B: 7308c2ecf20Sopenharmony_ci ret = RATEID_IDX_B; 7318c2ecf20Sopenharmony_ci break; 7328c2ecf20Sopenharmony_ci case RATR_INX_WIRELESS_MC: 7338c2ecf20Sopenharmony_ci if (wirelessmode == WIRELESS_MODE_B || 7348c2ecf20Sopenharmony_ci wirelessmode == WIRELESS_MODE_G || 7358c2ecf20Sopenharmony_ci wirelessmode == WIRELESS_MODE_N_24G || 7368c2ecf20Sopenharmony_ci wirelessmode == WIRELESS_MODE_AC_24G) 7378c2ecf20Sopenharmony_ci ret = RATEID_IDX_BG; 7388c2ecf20Sopenharmony_ci else 7398c2ecf20Sopenharmony_ci ret = RATEID_IDX_G; 7408c2ecf20Sopenharmony_ci break; 7418c2ecf20Sopenharmony_ci case RATR_INX_WIRELESS_AC_5N: 7428c2ecf20Sopenharmony_ci if (rtlphy->rf_type == RF_1T1R) 7438c2ecf20Sopenharmony_ci ret = RATEID_IDX_VHT_1SS; 7448c2ecf20Sopenharmony_ci else 7458c2ecf20Sopenharmony_ci ret = RATEID_IDX_VHT_2SS; 7468c2ecf20Sopenharmony_ci break; 7478c2ecf20Sopenharmony_ci case RATR_INX_WIRELESS_AC_24N: 7488c2ecf20Sopenharmony_ci if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) { 7498c2ecf20Sopenharmony_ci if (rtlphy->rf_type == RF_1T1R) 7508c2ecf20Sopenharmony_ci ret = RATEID_IDX_VHT_1SS; 7518c2ecf20Sopenharmony_ci else 7528c2ecf20Sopenharmony_ci ret = RATEID_IDX_VHT_2SS; 7538c2ecf20Sopenharmony_ci } else { 7548c2ecf20Sopenharmony_ci if (rtlphy->rf_type == RF_1T1R) 7558c2ecf20Sopenharmony_ci ret = RATEID_IDX_MIX1; 7568c2ecf20Sopenharmony_ci else 7578c2ecf20Sopenharmony_ci ret = RATEID_IDX_MIX2; 7588c2ecf20Sopenharmony_ci } 7598c2ecf20Sopenharmony_ci break; 7608c2ecf20Sopenharmony_ci default: 7618c2ecf20Sopenharmony_ci ret = RATEID_IDX_BGN_40M_2SS; 7628c2ecf20Sopenharmony_ci break; 7638c2ecf20Sopenharmony_ci } 7648c2ecf20Sopenharmony_ci return ret; 7658c2ecf20Sopenharmony_ci} 7668c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_mrate_idx_to_arfr_id); 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_cistatic void _rtl_txrate_selectmode(struct ieee80211_hw *hw, 7698c2ecf20Sopenharmony_ci struct ieee80211_sta *sta, 7708c2ecf20Sopenharmony_ci struct rtl_tcb_desc *tcb_desc) 7718c2ecf20Sopenharmony_ci{ 7728c2ecf20Sopenharmony_ci#define SET_RATE_ID(rate_id) \ 7738c2ecf20Sopenharmony_ci ({typeof(rate_id) _id = rate_id; \ 7748c2ecf20Sopenharmony_ci ((rtlpriv->cfg->spec_ver & RTL_SPEC_NEW_RATEID) ? \ 7758c2ecf20Sopenharmony_ci rtl_mrate_idx_to_arfr_id(hw, _id, \ 7768c2ecf20Sopenharmony_ci (sta_entry ? sta_entry->wireless_mode : \ 7778c2ecf20Sopenharmony_ci WIRELESS_MODE_G)) : \ 7788c2ecf20Sopenharmony_ci _id); }) 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 7818c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 7828c2ecf20Sopenharmony_ci struct rtl_sta_info *sta_entry = NULL; 7838c2ecf20Sopenharmony_ci u8 ratr_index = SET_RATE_ID(RATR_INX_WIRELESS_MC); 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci if (sta) { 7868c2ecf20Sopenharmony_ci sta_entry = (struct rtl_sta_info *) sta->drv_priv; 7878c2ecf20Sopenharmony_ci ratr_index = sta_entry->ratr_index; 7888c2ecf20Sopenharmony_ci } 7898c2ecf20Sopenharmony_ci if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { 7908c2ecf20Sopenharmony_ci if (mac->opmode == NL80211_IFTYPE_STATION) { 7918c2ecf20Sopenharmony_ci tcb_desc->ratr_index = 0; 7928c2ecf20Sopenharmony_ci } else if (mac->opmode == NL80211_IFTYPE_ADHOC || 7938c2ecf20Sopenharmony_ci mac->opmode == NL80211_IFTYPE_MESH_POINT) { 7948c2ecf20Sopenharmony_ci if (tcb_desc->multicast || tcb_desc->broadcast) { 7958c2ecf20Sopenharmony_ci tcb_desc->hw_rate = 7968c2ecf20Sopenharmony_ci rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; 7978c2ecf20Sopenharmony_ci tcb_desc->use_driver_rate = 1; 7988c2ecf20Sopenharmony_ci tcb_desc->ratr_index = 7998c2ecf20Sopenharmony_ci SET_RATE_ID(RATR_INX_WIRELESS_MC); 8008c2ecf20Sopenharmony_ci } else { 8018c2ecf20Sopenharmony_ci tcb_desc->ratr_index = ratr_index; 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci } else if (mac->opmode == NL80211_IFTYPE_AP) { 8048c2ecf20Sopenharmony_ci tcb_desc->ratr_index = ratr_index; 8058c2ecf20Sopenharmony_ci } 8068c2ecf20Sopenharmony_ci } 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci if (rtlpriv->dm.useramask) { 8098c2ecf20Sopenharmony_ci tcb_desc->ratr_index = ratr_index; 8108c2ecf20Sopenharmony_ci /* TODO we will differentiate adhoc and station future */ 8118c2ecf20Sopenharmony_ci if (mac->opmode == NL80211_IFTYPE_STATION || 8128c2ecf20Sopenharmony_ci mac->opmode == NL80211_IFTYPE_MESH_POINT) { 8138c2ecf20Sopenharmony_ci tcb_desc->mac_id = 0; 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci if (sta && 8168c2ecf20Sopenharmony_ci (rtlpriv->cfg->spec_ver & RTL_SPEC_NEW_RATEID)) 8178c2ecf20Sopenharmony_ci ; /* use sta_entry->ratr_index */ 8188c2ecf20Sopenharmony_ci else if (mac->mode == WIRELESS_MODE_AC_5G) 8198c2ecf20Sopenharmony_ci tcb_desc->ratr_index = 8208c2ecf20Sopenharmony_ci SET_RATE_ID(RATR_INX_WIRELESS_AC_5N); 8218c2ecf20Sopenharmony_ci else if (mac->mode == WIRELESS_MODE_AC_24G) 8228c2ecf20Sopenharmony_ci tcb_desc->ratr_index = 8238c2ecf20Sopenharmony_ci SET_RATE_ID(RATR_INX_WIRELESS_AC_24N); 8248c2ecf20Sopenharmony_ci else if (mac->mode == WIRELESS_MODE_N_24G) 8258c2ecf20Sopenharmony_ci tcb_desc->ratr_index = 8268c2ecf20Sopenharmony_ci SET_RATE_ID(RATR_INX_WIRELESS_NGB); 8278c2ecf20Sopenharmony_ci else if (mac->mode == WIRELESS_MODE_N_5G) 8288c2ecf20Sopenharmony_ci tcb_desc->ratr_index = 8298c2ecf20Sopenharmony_ci SET_RATE_ID(RATR_INX_WIRELESS_NG); 8308c2ecf20Sopenharmony_ci else if (mac->mode & WIRELESS_MODE_G) 8318c2ecf20Sopenharmony_ci tcb_desc->ratr_index = 8328c2ecf20Sopenharmony_ci SET_RATE_ID(RATR_INX_WIRELESS_GB); 8338c2ecf20Sopenharmony_ci else if (mac->mode & WIRELESS_MODE_B) 8348c2ecf20Sopenharmony_ci tcb_desc->ratr_index = 8358c2ecf20Sopenharmony_ci SET_RATE_ID(RATR_INX_WIRELESS_B); 8368c2ecf20Sopenharmony_ci else if (mac->mode & WIRELESS_MODE_A) 8378c2ecf20Sopenharmony_ci tcb_desc->ratr_index = 8388c2ecf20Sopenharmony_ci SET_RATE_ID(RATR_INX_WIRELESS_G); 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci } else if (mac->opmode == NL80211_IFTYPE_AP || 8418c2ecf20Sopenharmony_ci mac->opmode == NL80211_IFTYPE_ADHOC) { 8428c2ecf20Sopenharmony_ci if (NULL != sta) { 8438c2ecf20Sopenharmony_ci if (sta->aid > 0) 8448c2ecf20Sopenharmony_ci tcb_desc->mac_id = sta->aid + 1; 8458c2ecf20Sopenharmony_ci else 8468c2ecf20Sopenharmony_ci tcb_desc->mac_id = 1; 8478c2ecf20Sopenharmony_ci } else { 8488c2ecf20Sopenharmony_ci tcb_desc->mac_id = 0; 8498c2ecf20Sopenharmony_ci } 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci } 8528c2ecf20Sopenharmony_ci#undef SET_RATE_ID 8538c2ecf20Sopenharmony_ci} 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_cistatic void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, 8568c2ecf20Sopenharmony_ci struct ieee80211_sta *sta, 8578c2ecf20Sopenharmony_ci struct rtl_tcb_desc *tcb_desc) 8588c2ecf20Sopenharmony_ci{ 8598c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 8608c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci tcb_desc->packet_bw = false; 8638c2ecf20Sopenharmony_ci if (!sta) 8648c2ecf20Sopenharmony_ci return; 8658c2ecf20Sopenharmony_ci if (mac->opmode == NL80211_IFTYPE_AP || 8668c2ecf20Sopenharmony_ci mac->opmode == NL80211_IFTYPE_ADHOC || 8678c2ecf20Sopenharmony_ci mac->opmode == NL80211_IFTYPE_MESH_POINT) { 8688c2ecf20Sopenharmony_ci if (!(sta->ht_cap.ht_supported) || 8698c2ecf20Sopenharmony_ci !(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) 8708c2ecf20Sopenharmony_ci return; 8718c2ecf20Sopenharmony_ci } else if (mac->opmode == NL80211_IFTYPE_STATION) { 8728c2ecf20Sopenharmony_ci if (!mac->bw_40 || !(sta->ht_cap.ht_supported)) 8738c2ecf20Sopenharmony_ci return; 8748c2ecf20Sopenharmony_ci } 8758c2ecf20Sopenharmony_ci if (tcb_desc->multicast || tcb_desc->broadcast) 8768c2ecf20Sopenharmony_ci return; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci /*use legency rate, shall use 20MHz */ 8798c2ecf20Sopenharmony_ci if (tcb_desc->hw_rate <= rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]) 8808c2ecf20Sopenharmony_ci return; 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci tcb_desc->packet_bw = HT_CHANNEL_WIDTH_20_40; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci if (rtlpriv->cfg->spec_ver & RTL_SPEC_SUPPORT_VHT) { 8858c2ecf20Sopenharmony_ci if (mac->opmode == NL80211_IFTYPE_AP || 8868c2ecf20Sopenharmony_ci mac->opmode == NL80211_IFTYPE_ADHOC || 8878c2ecf20Sopenharmony_ci mac->opmode == NL80211_IFTYPE_MESH_POINT) { 8888c2ecf20Sopenharmony_ci if (!(sta->vht_cap.vht_supported)) 8898c2ecf20Sopenharmony_ci return; 8908c2ecf20Sopenharmony_ci } else if (mac->opmode == NL80211_IFTYPE_STATION) { 8918c2ecf20Sopenharmony_ci if (!mac->bw_80 || 8928c2ecf20Sopenharmony_ci !(sta->vht_cap.vht_supported)) 8938c2ecf20Sopenharmony_ci return; 8948c2ecf20Sopenharmony_ci } 8958c2ecf20Sopenharmony_ci if (tcb_desc->hw_rate <= 8968c2ecf20Sopenharmony_ci rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS15]) 8978c2ecf20Sopenharmony_ci return; 8988c2ecf20Sopenharmony_ci tcb_desc->packet_bw = HT_CHANNEL_WIDTH_80; 8998c2ecf20Sopenharmony_ci } 9008c2ecf20Sopenharmony_ci} 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_cistatic u8 _rtl_get_vht_highest_n_rate(struct ieee80211_hw *hw, 9038c2ecf20Sopenharmony_ci struct ieee80211_sta *sta) 9048c2ecf20Sopenharmony_ci{ 9058c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 9068c2ecf20Sopenharmony_ci struct rtl_phy *rtlphy = &(rtlpriv->phy); 9078c2ecf20Sopenharmony_ci u8 hw_rate; 9088c2ecf20Sopenharmony_ci u16 tx_mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.tx_mcs_map); 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci if ((get_rf_type(rtlphy) == RF_2T2R) && 9118c2ecf20Sopenharmony_ci (tx_mcs_map & 0x000c) != 0x000c) { 9128c2ecf20Sopenharmony_ci if ((tx_mcs_map & 0x000c) >> 2 == 9138c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_SUPPORT_0_7) 9148c2ecf20Sopenharmony_ci hw_rate = 9158c2ecf20Sopenharmony_ci rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS7]; 9168c2ecf20Sopenharmony_ci else if ((tx_mcs_map & 0x000c) >> 2 == 9178c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_SUPPORT_0_8) 9188c2ecf20Sopenharmony_ci hw_rate = 9198c2ecf20Sopenharmony_ci rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS8]; 9208c2ecf20Sopenharmony_ci else 9218c2ecf20Sopenharmony_ci hw_rate = 9228c2ecf20Sopenharmony_ci rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS9]; 9238c2ecf20Sopenharmony_ci } else { 9248c2ecf20Sopenharmony_ci if ((tx_mcs_map & 0x0003) == 9258c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_SUPPORT_0_7) 9268c2ecf20Sopenharmony_ci hw_rate = 9278c2ecf20Sopenharmony_ci rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS7]; 9288c2ecf20Sopenharmony_ci else if ((tx_mcs_map & 0x0003) == 9298c2ecf20Sopenharmony_ci IEEE80211_VHT_MCS_SUPPORT_0_8) 9308c2ecf20Sopenharmony_ci hw_rate = 9318c2ecf20Sopenharmony_ci rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS8]; 9328c2ecf20Sopenharmony_ci else 9338c2ecf20Sopenharmony_ci hw_rate = 9348c2ecf20Sopenharmony_ci rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS9]; 9358c2ecf20Sopenharmony_ci } 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci return hw_rate; 9388c2ecf20Sopenharmony_ci} 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_cistatic u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw, 9418c2ecf20Sopenharmony_ci struct ieee80211_sta *sta) 9428c2ecf20Sopenharmony_ci{ 9438c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 9448c2ecf20Sopenharmony_ci struct rtl_phy *rtlphy = &rtlpriv->phy; 9458c2ecf20Sopenharmony_ci u8 hw_rate; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci if (get_rf_type(rtlphy) == RF_2T2R && 9488c2ecf20Sopenharmony_ci sta->ht_cap.mcs.rx_mask[1] != 0) 9498c2ecf20Sopenharmony_ci hw_rate = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS15]; 9508c2ecf20Sopenharmony_ci else 9518c2ecf20Sopenharmony_ci hw_rate = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS7]; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci return hw_rate; 9548c2ecf20Sopenharmony_ci} 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci/* mac80211's rate_idx is like this: 9578c2ecf20Sopenharmony_ci * 9588c2ecf20Sopenharmony_ci * 2.4G band:rx_status->band == NL80211_BAND_2GHZ 9598c2ecf20Sopenharmony_ci * 9608c2ecf20Sopenharmony_ci * B/G rate: 9618c2ecf20Sopenharmony_ci * (rx_status->flag & RX_FLAG_HT) = 0, 9628c2ecf20Sopenharmony_ci * DESC_RATE1M-->DESC_RATE54M ==> idx is 0-->11, 9638c2ecf20Sopenharmony_ci * 9648c2ecf20Sopenharmony_ci * N rate: 9658c2ecf20Sopenharmony_ci * (rx_status->flag & RX_FLAG_HT) = 1, 9668c2ecf20Sopenharmony_ci * DESC_RATEMCS0-->DESC_RATEMCS15 ==> idx is 0-->15 9678c2ecf20Sopenharmony_ci * 9688c2ecf20Sopenharmony_ci * 5G band:rx_status->band == NL80211_BAND_5GHZ 9698c2ecf20Sopenharmony_ci * A rate: 9708c2ecf20Sopenharmony_ci * (rx_status->flag & RX_FLAG_HT) = 0, 9718c2ecf20Sopenharmony_ci * DESC_RATE6M-->DESC_RATE54M ==> idx is 0-->7, 9728c2ecf20Sopenharmony_ci * 9738c2ecf20Sopenharmony_ci * N rate: 9748c2ecf20Sopenharmony_ci * (rx_status->flag & RX_FLAG_HT) = 1, 9758c2ecf20Sopenharmony_ci * DESC_RATEMCS0-->DESC_RATEMCS15 ==> idx is 0-->15 9768c2ecf20Sopenharmony_ci * 9778c2ecf20Sopenharmony_ci * VHT rates: 9788c2ecf20Sopenharmony_ci * DESC_RATEVHT1SS_MCS0-->DESC_RATEVHT1SS_MCS9 ==> idx is 0-->9 9798c2ecf20Sopenharmony_ci * DESC_RATEVHT2SS_MCS0-->DESC_RATEVHT2SS_MCS9 ==> idx is 0-->9 9808c2ecf20Sopenharmony_ci */ 9818c2ecf20Sopenharmony_ciint rtlwifi_rate_mapping(struct ieee80211_hw *hw, bool isht, bool isvht, 9828c2ecf20Sopenharmony_ci u8 desc_rate) 9838c2ecf20Sopenharmony_ci{ 9848c2ecf20Sopenharmony_ci int rate_idx; 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci if (isvht) { 9878c2ecf20Sopenharmony_ci switch (desc_rate) { 9888c2ecf20Sopenharmony_ci case DESC_RATEVHT1SS_MCS0: 9898c2ecf20Sopenharmony_ci rate_idx = 0; 9908c2ecf20Sopenharmony_ci break; 9918c2ecf20Sopenharmony_ci case DESC_RATEVHT1SS_MCS1: 9928c2ecf20Sopenharmony_ci rate_idx = 1; 9938c2ecf20Sopenharmony_ci break; 9948c2ecf20Sopenharmony_ci case DESC_RATEVHT1SS_MCS2: 9958c2ecf20Sopenharmony_ci rate_idx = 2; 9968c2ecf20Sopenharmony_ci break; 9978c2ecf20Sopenharmony_ci case DESC_RATEVHT1SS_MCS3: 9988c2ecf20Sopenharmony_ci rate_idx = 3; 9998c2ecf20Sopenharmony_ci break; 10008c2ecf20Sopenharmony_ci case DESC_RATEVHT1SS_MCS4: 10018c2ecf20Sopenharmony_ci rate_idx = 4; 10028c2ecf20Sopenharmony_ci break; 10038c2ecf20Sopenharmony_ci case DESC_RATEVHT1SS_MCS5: 10048c2ecf20Sopenharmony_ci rate_idx = 5; 10058c2ecf20Sopenharmony_ci break; 10068c2ecf20Sopenharmony_ci case DESC_RATEVHT1SS_MCS6: 10078c2ecf20Sopenharmony_ci rate_idx = 6; 10088c2ecf20Sopenharmony_ci break; 10098c2ecf20Sopenharmony_ci case DESC_RATEVHT1SS_MCS7: 10108c2ecf20Sopenharmony_ci rate_idx = 7; 10118c2ecf20Sopenharmony_ci break; 10128c2ecf20Sopenharmony_ci case DESC_RATEVHT1SS_MCS8: 10138c2ecf20Sopenharmony_ci rate_idx = 8; 10148c2ecf20Sopenharmony_ci break; 10158c2ecf20Sopenharmony_ci case DESC_RATEVHT1SS_MCS9: 10168c2ecf20Sopenharmony_ci rate_idx = 9; 10178c2ecf20Sopenharmony_ci break; 10188c2ecf20Sopenharmony_ci case DESC_RATEVHT2SS_MCS0: 10198c2ecf20Sopenharmony_ci rate_idx = 0; 10208c2ecf20Sopenharmony_ci break; 10218c2ecf20Sopenharmony_ci case DESC_RATEVHT2SS_MCS1: 10228c2ecf20Sopenharmony_ci rate_idx = 1; 10238c2ecf20Sopenharmony_ci break; 10248c2ecf20Sopenharmony_ci case DESC_RATEVHT2SS_MCS2: 10258c2ecf20Sopenharmony_ci rate_idx = 2; 10268c2ecf20Sopenharmony_ci break; 10278c2ecf20Sopenharmony_ci case DESC_RATEVHT2SS_MCS3: 10288c2ecf20Sopenharmony_ci rate_idx = 3; 10298c2ecf20Sopenharmony_ci break; 10308c2ecf20Sopenharmony_ci case DESC_RATEVHT2SS_MCS4: 10318c2ecf20Sopenharmony_ci rate_idx = 4; 10328c2ecf20Sopenharmony_ci break; 10338c2ecf20Sopenharmony_ci case DESC_RATEVHT2SS_MCS5: 10348c2ecf20Sopenharmony_ci rate_idx = 5; 10358c2ecf20Sopenharmony_ci break; 10368c2ecf20Sopenharmony_ci case DESC_RATEVHT2SS_MCS6: 10378c2ecf20Sopenharmony_ci rate_idx = 6; 10388c2ecf20Sopenharmony_ci break; 10398c2ecf20Sopenharmony_ci case DESC_RATEVHT2SS_MCS7: 10408c2ecf20Sopenharmony_ci rate_idx = 7; 10418c2ecf20Sopenharmony_ci break; 10428c2ecf20Sopenharmony_ci case DESC_RATEVHT2SS_MCS8: 10438c2ecf20Sopenharmony_ci rate_idx = 8; 10448c2ecf20Sopenharmony_ci break; 10458c2ecf20Sopenharmony_ci case DESC_RATEVHT2SS_MCS9: 10468c2ecf20Sopenharmony_ci rate_idx = 9; 10478c2ecf20Sopenharmony_ci break; 10488c2ecf20Sopenharmony_ci default: 10498c2ecf20Sopenharmony_ci rate_idx = 0; 10508c2ecf20Sopenharmony_ci break; 10518c2ecf20Sopenharmony_ci } 10528c2ecf20Sopenharmony_ci return rate_idx; 10538c2ecf20Sopenharmony_ci } 10548c2ecf20Sopenharmony_ci if (false == isht) { 10558c2ecf20Sopenharmony_ci if (NL80211_BAND_2GHZ == hw->conf.chandef.chan->band) { 10568c2ecf20Sopenharmony_ci switch (desc_rate) { 10578c2ecf20Sopenharmony_ci case DESC_RATE1M: 10588c2ecf20Sopenharmony_ci rate_idx = 0; 10598c2ecf20Sopenharmony_ci break; 10608c2ecf20Sopenharmony_ci case DESC_RATE2M: 10618c2ecf20Sopenharmony_ci rate_idx = 1; 10628c2ecf20Sopenharmony_ci break; 10638c2ecf20Sopenharmony_ci case DESC_RATE5_5M: 10648c2ecf20Sopenharmony_ci rate_idx = 2; 10658c2ecf20Sopenharmony_ci break; 10668c2ecf20Sopenharmony_ci case DESC_RATE11M: 10678c2ecf20Sopenharmony_ci rate_idx = 3; 10688c2ecf20Sopenharmony_ci break; 10698c2ecf20Sopenharmony_ci case DESC_RATE6M: 10708c2ecf20Sopenharmony_ci rate_idx = 4; 10718c2ecf20Sopenharmony_ci break; 10728c2ecf20Sopenharmony_ci case DESC_RATE9M: 10738c2ecf20Sopenharmony_ci rate_idx = 5; 10748c2ecf20Sopenharmony_ci break; 10758c2ecf20Sopenharmony_ci case DESC_RATE12M: 10768c2ecf20Sopenharmony_ci rate_idx = 6; 10778c2ecf20Sopenharmony_ci break; 10788c2ecf20Sopenharmony_ci case DESC_RATE18M: 10798c2ecf20Sopenharmony_ci rate_idx = 7; 10808c2ecf20Sopenharmony_ci break; 10818c2ecf20Sopenharmony_ci case DESC_RATE24M: 10828c2ecf20Sopenharmony_ci rate_idx = 8; 10838c2ecf20Sopenharmony_ci break; 10848c2ecf20Sopenharmony_ci case DESC_RATE36M: 10858c2ecf20Sopenharmony_ci rate_idx = 9; 10868c2ecf20Sopenharmony_ci break; 10878c2ecf20Sopenharmony_ci case DESC_RATE48M: 10888c2ecf20Sopenharmony_ci rate_idx = 10; 10898c2ecf20Sopenharmony_ci break; 10908c2ecf20Sopenharmony_ci case DESC_RATE54M: 10918c2ecf20Sopenharmony_ci rate_idx = 11; 10928c2ecf20Sopenharmony_ci break; 10938c2ecf20Sopenharmony_ci default: 10948c2ecf20Sopenharmony_ci rate_idx = 0; 10958c2ecf20Sopenharmony_ci break; 10968c2ecf20Sopenharmony_ci } 10978c2ecf20Sopenharmony_ci } else { 10988c2ecf20Sopenharmony_ci switch (desc_rate) { 10998c2ecf20Sopenharmony_ci case DESC_RATE6M: 11008c2ecf20Sopenharmony_ci rate_idx = 0; 11018c2ecf20Sopenharmony_ci break; 11028c2ecf20Sopenharmony_ci case DESC_RATE9M: 11038c2ecf20Sopenharmony_ci rate_idx = 1; 11048c2ecf20Sopenharmony_ci break; 11058c2ecf20Sopenharmony_ci case DESC_RATE12M: 11068c2ecf20Sopenharmony_ci rate_idx = 2; 11078c2ecf20Sopenharmony_ci break; 11088c2ecf20Sopenharmony_ci case DESC_RATE18M: 11098c2ecf20Sopenharmony_ci rate_idx = 3; 11108c2ecf20Sopenharmony_ci break; 11118c2ecf20Sopenharmony_ci case DESC_RATE24M: 11128c2ecf20Sopenharmony_ci rate_idx = 4; 11138c2ecf20Sopenharmony_ci break; 11148c2ecf20Sopenharmony_ci case DESC_RATE36M: 11158c2ecf20Sopenharmony_ci rate_idx = 5; 11168c2ecf20Sopenharmony_ci break; 11178c2ecf20Sopenharmony_ci case DESC_RATE48M: 11188c2ecf20Sopenharmony_ci rate_idx = 6; 11198c2ecf20Sopenharmony_ci break; 11208c2ecf20Sopenharmony_ci case DESC_RATE54M: 11218c2ecf20Sopenharmony_ci rate_idx = 7; 11228c2ecf20Sopenharmony_ci break; 11238c2ecf20Sopenharmony_ci default: 11248c2ecf20Sopenharmony_ci rate_idx = 0; 11258c2ecf20Sopenharmony_ci break; 11268c2ecf20Sopenharmony_ci } 11278c2ecf20Sopenharmony_ci } 11288c2ecf20Sopenharmony_ci } else { 11298c2ecf20Sopenharmony_ci switch (desc_rate) { 11308c2ecf20Sopenharmony_ci case DESC_RATEMCS0: 11318c2ecf20Sopenharmony_ci rate_idx = 0; 11328c2ecf20Sopenharmony_ci break; 11338c2ecf20Sopenharmony_ci case DESC_RATEMCS1: 11348c2ecf20Sopenharmony_ci rate_idx = 1; 11358c2ecf20Sopenharmony_ci break; 11368c2ecf20Sopenharmony_ci case DESC_RATEMCS2: 11378c2ecf20Sopenharmony_ci rate_idx = 2; 11388c2ecf20Sopenharmony_ci break; 11398c2ecf20Sopenharmony_ci case DESC_RATEMCS3: 11408c2ecf20Sopenharmony_ci rate_idx = 3; 11418c2ecf20Sopenharmony_ci break; 11428c2ecf20Sopenharmony_ci case DESC_RATEMCS4: 11438c2ecf20Sopenharmony_ci rate_idx = 4; 11448c2ecf20Sopenharmony_ci break; 11458c2ecf20Sopenharmony_ci case DESC_RATEMCS5: 11468c2ecf20Sopenharmony_ci rate_idx = 5; 11478c2ecf20Sopenharmony_ci break; 11488c2ecf20Sopenharmony_ci case DESC_RATEMCS6: 11498c2ecf20Sopenharmony_ci rate_idx = 6; 11508c2ecf20Sopenharmony_ci break; 11518c2ecf20Sopenharmony_ci case DESC_RATEMCS7: 11528c2ecf20Sopenharmony_ci rate_idx = 7; 11538c2ecf20Sopenharmony_ci break; 11548c2ecf20Sopenharmony_ci case DESC_RATEMCS8: 11558c2ecf20Sopenharmony_ci rate_idx = 8; 11568c2ecf20Sopenharmony_ci break; 11578c2ecf20Sopenharmony_ci case DESC_RATEMCS9: 11588c2ecf20Sopenharmony_ci rate_idx = 9; 11598c2ecf20Sopenharmony_ci break; 11608c2ecf20Sopenharmony_ci case DESC_RATEMCS10: 11618c2ecf20Sopenharmony_ci rate_idx = 10; 11628c2ecf20Sopenharmony_ci break; 11638c2ecf20Sopenharmony_ci case DESC_RATEMCS11: 11648c2ecf20Sopenharmony_ci rate_idx = 11; 11658c2ecf20Sopenharmony_ci break; 11668c2ecf20Sopenharmony_ci case DESC_RATEMCS12: 11678c2ecf20Sopenharmony_ci rate_idx = 12; 11688c2ecf20Sopenharmony_ci break; 11698c2ecf20Sopenharmony_ci case DESC_RATEMCS13: 11708c2ecf20Sopenharmony_ci rate_idx = 13; 11718c2ecf20Sopenharmony_ci break; 11728c2ecf20Sopenharmony_ci case DESC_RATEMCS14: 11738c2ecf20Sopenharmony_ci rate_idx = 14; 11748c2ecf20Sopenharmony_ci break; 11758c2ecf20Sopenharmony_ci case DESC_RATEMCS15: 11768c2ecf20Sopenharmony_ci rate_idx = 15; 11778c2ecf20Sopenharmony_ci break; 11788c2ecf20Sopenharmony_ci default: 11798c2ecf20Sopenharmony_ci rate_idx = 0; 11808c2ecf20Sopenharmony_ci break; 11818c2ecf20Sopenharmony_ci } 11828c2ecf20Sopenharmony_ci } 11838c2ecf20Sopenharmony_ci return rate_idx; 11848c2ecf20Sopenharmony_ci} 11858c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtlwifi_rate_mapping); 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_cistatic u8 _rtl_get_tx_hw_rate(struct ieee80211_hw *hw, 11888c2ecf20Sopenharmony_ci struct ieee80211_tx_info *info) 11898c2ecf20Sopenharmony_ci{ 11908c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 11918c2ecf20Sopenharmony_ci struct ieee80211_tx_rate *r = &info->status.rates[0]; 11928c2ecf20Sopenharmony_ci struct ieee80211_rate *txrate; 11938c2ecf20Sopenharmony_ci u8 hw_value = 0x0; 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci if (r->flags & IEEE80211_TX_RC_MCS) { 11968c2ecf20Sopenharmony_ci /* HT MCS0-15 */ 11978c2ecf20Sopenharmony_ci hw_value = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS15] - 15 + 11988c2ecf20Sopenharmony_ci r->idx; 11998c2ecf20Sopenharmony_ci } else if (r->flags & IEEE80211_TX_RC_VHT_MCS) { 12008c2ecf20Sopenharmony_ci /* VHT MCS0-9, NSS */ 12018c2ecf20Sopenharmony_ci if (ieee80211_rate_get_vht_nss(r) == 2) 12028c2ecf20Sopenharmony_ci hw_value = rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS9]; 12038c2ecf20Sopenharmony_ci else 12048c2ecf20Sopenharmony_ci hw_value = rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS9]; 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci hw_value = hw_value - 9 + ieee80211_rate_get_vht_mcs(r); 12078c2ecf20Sopenharmony_ci } else { 12088c2ecf20Sopenharmony_ci /* legacy */ 12098c2ecf20Sopenharmony_ci txrate = ieee80211_get_tx_rate(hw, info); 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci if (txrate) 12128c2ecf20Sopenharmony_ci hw_value = txrate->hw_value; 12138c2ecf20Sopenharmony_ci } 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci /* check 5G band */ 12168c2ecf20Sopenharmony_ci if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G && 12178c2ecf20Sopenharmony_ci hw_value < rtlpriv->cfg->maps[RTL_RC_OFDM_RATE6M]) 12188c2ecf20Sopenharmony_ci hw_value = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE6M]; 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci return hw_value; 12218c2ecf20Sopenharmony_ci} 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_civoid rtl_get_tcb_desc(struct ieee80211_hw *hw, 12248c2ecf20Sopenharmony_ci struct ieee80211_tx_info *info, 12258c2ecf20Sopenharmony_ci struct ieee80211_sta *sta, 12268c2ecf20Sopenharmony_ci struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc) 12278c2ecf20Sopenharmony_ci{ 12288c2ecf20Sopenharmony_ci#define SET_RATE_ID(rate_id) \ 12298c2ecf20Sopenharmony_ci ({typeof(rate_id) _id = rate_id; \ 12308c2ecf20Sopenharmony_ci ((rtlpriv->cfg->spec_ver & RTL_SPEC_NEW_RATEID) ? \ 12318c2ecf20Sopenharmony_ci rtl_mrate_idx_to_arfr_id(hw, _id, \ 12328c2ecf20Sopenharmony_ci (sta_entry ? sta_entry->wireless_mode : \ 12338c2ecf20Sopenharmony_ci WIRELESS_MODE_G)) : \ 12348c2ecf20Sopenharmony_ci _id); }) 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 12378c2ecf20Sopenharmony_ci struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); 12388c2ecf20Sopenharmony_ci struct ieee80211_hdr *hdr = rtl_get_hdr(skb); 12398c2ecf20Sopenharmony_ci struct rtl_sta_info *sta_entry = 12408c2ecf20Sopenharmony_ci (sta ? (struct rtl_sta_info *)sta->drv_priv : NULL); 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci __le16 fc = rtl_get_fc(skb); 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci tcb_desc->hw_rate = _rtl_get_tx_hw_rate(hw, info); 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci if (rtl_is_tx_report_skb(hw, skb)) 12478c2ecf20Sopenharmony_ci tcb_desc->use_spe_rpt = 1; 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci if (ieee80211_is_data(fc)) { 12508c2ecf20Sopenharmony_ci /* 12518c2ecf20Sopenharmony_ci *we set data rate INX 0 12528c2ecf20Sopenharmony_ci *in rtl_rc.c if skb is special data or 12538c2ecf20Sopenharmony_ci *mgt which need low data rate. 12548c2ecf20Sopenharmony_ci */ 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci /* 12578c2ecf20Sopenharmony_ci *So tcb_desc->hw_rate is just used for 12588c2ecf20Sopenharmony_ci *special data and mgt frames 12598c2ecf20Sopenharmony_ci */ 12608c2ecf20Sopenharmony_ci if (info->control.rates[0].idx == 0 || 12618c2ecf20Sopenharmony_ci ieee80211_is_nullfunc(fc)) { 12628c2ecf20Sopenharmony_ci tcb_desc->use_driver_rate = true; 12638c2ecf20Sopenharmony_ci tcb_desc->ratr_index = 12648c2ecf20Sopenharmony_ci SET_RATE_ID(RATR_INX_WIRELESS_MC); 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci tcb_desc->disable_ratefallback = 1; 12678c2ecf20Sopenharmony_ci } else { 12688c2ecf20Sopenharmony_ci /* 12698c2ecf20Sopenharmony_ci *because hw will nerver use hw_rate 12708c2ecf20Sopenharmony_ci *when tcb_desc->use_driver_rate = false 12718c2ecf20Sopenharmony_ci *so we never set highest N rate here, 12728c2ecf20Sopenharmony_ci *and N rate will all be controlled by FW 12738c2ecf20Sopenharmony_ci *when tcb_desc->use_driver_rate = false 12748c2ecf20Sopenharmony_ci */ 12758c2ecf20Sopenharmony_ci if (sta && sta->vht_cap.vht_supported) { 12768c2ecf20Sopenharmony_ci tcb_desc->hw_rate = 12778c2ecf20Sopenharmony_ci _rtl_get_vht_highest_n_rate(hw, sta); 12788c2ecf20Sopenharmony_ci } else { 12798c2ecf20Sopenharmony_ci if (sta && sta->ht_cap.ht_supported) { 12808c2ecf20Sopenharmony_ci tcb_desc->hw_rate = 12818c2ecf20Sopenharmony_ci _rtl_get_highest_n_rate(hw, sta); 12828c2ecf20Sopenharmony_ci } else { 12838c2ecf20Sopenharmony_ci if (rtlmac->mode == WIRELESS_MODE_B) { 12848c2ecf20Sopenharmony_ci tcb_desc->hw_rate = 12858c2ecf20Sopenharmony_ci rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]; 12868c2ecf20Sopenharmony_ci } else { 12878c2ecf20Sopenharmony_ci tcb_desc->hw_rate = 12888c2ecf20Sopenharmony_ci rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]; 12898c2ecf20Sopenharmony_ci } 12908c2ecf20Sopenharmony_ci } 12918c2ecf20Sopenharmony_ci } 12928c2ecf20Sopenharmony_ci } 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci if (is_multicast_ether_addr(hdr->addr1)) 12958c2ecf20Sopenharmony_ci tcb_desc->multicast = 1; 12968c2ecf20Sopenharmony_ci else if (is_broadcast_ether_addr(hdr->addr1)) 12978c2ecf20Sopenharmony_ci tcb_desc->broadcast = 1; 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci _rtl_txrate_selectmode(hw, sta, tcb_desc); 13008c2ecf20Sopenharmony_ci _rtl_query_bandwidth_mode(hw, sta, tcb_desc); 13018c2ecf20Sopenharmony_ci _rtl_qurey_shortpreamble_mode(hw, tcb_desc, info); 13028c2ecf20Sopenharmony_ci _rtl_query_shortgi(hw, sta, tcb_desc, info); 13038c2ecf20Sopenharmony_ci _rtl_query_protection_mode(hw, tcb_desc, info); 13048c2ecf20Sopenharmony_ci } else { 13058c2ecf20Sopenharmony_ci tcb_desc->use_driver_rate = true; 13068c2ecf20Sopenharmony_ci tcb_desc->ratr_index = SET_RATE_ID(RATR_INX_WIRELESS_MC); 13078c2ecf20Sopenharmony_ci tcb_desc->disable_ratefallback = 1; 13088c2ecf20Sopenharmony_ci tcb_desc->mac_id = 0; 13098c2ecf20Sopenharmony_ci tcb_desc->packet_bw = false; 13108c2ecf20Sopenharmony_ci } 13118c2ecf20Sopenharmony_ci#undef SET_RATE_ID 13128c2ecf20Sopenharmony_ci} 13138c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_get_tcb_desc); 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_cibool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb) 13168c2ecf20Sopenharmony_ci{ 13178c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 13188c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 13198c2ecf20Sopenharmony_ci __le16 fc = rtl_get_fc(skb); 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci if (rtlpriv->dm.supp_phymode_switch && 13228c2ecf20Sopenharmony_ci mac->link_state < MAC80211_LINKED && 13238c2ecf20Sopenharmony_ci (ieee80211_is_auth(fc) || ieee80211_is_probe_req(fc))) { 13248c2ecf20Sopenharmony_ci if (rtlpriv->cfg->ops->chk_switch_dmdp) 13258c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->chk_switch_dmdp(hw); 13268c2ecf20Sopenharmony_ci } 13278c2ecf20Sopenharmony_ci if (ieee80211_is_auth(fc)) { 13288c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n"); 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci mac->link_state = MAC80211_LINKING; 13318c2ecf20Sopenharmony_ci /* Dul mac */ 13328c2ecf20Sopenharmony_ci rtlpriv->phy.need_iqk = true; 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_ci } 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci return true; 13378c2ecf20Sopenharmony_ci} 13388c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_tx_mgmt_proc); 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_cistruct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, u8 *sa, 13418c2ecf20Sopenharmony_ci u8 *bssid, u16 tid); 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_cistatic void process_agg_start(struct ieee80211_hw *hw, 13448c2ecf20Sopenharmony_ci struct ieee80211_hdr *hdr, u16 tid) 13458c2ecf20Sopenharmony_ci{ 13468c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 13478c2ecf20Sopenharmony_ci struct ieee80211_rx_status rx_status = { 0 }; 13488c2ecf20Sopenharmony_ci struct sk_buff *skb_delba = NULL; 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci skb_delba = rtl_make_del_ba(hw, hdr->addr2, hdr->addr3, tid); 13518c2ecf20Sopenharmony_ci if (skb_delba) { 13528c2ecf20Sopenharmony_ci rx_status.freq = hw->conf.chandef.chan->center_freq; 13538c2ecf20Sopenharmony_ci rx_status.band = hw->conf.chandef.chan->band; 13548c2ecf20Sopenharmony_ci rx_status.flag |= RX_FLAG_DECRYPTED; 13558c2ecf20Sopenharmony_ci rx_status.flag |= RX_FLAG_MACTIME_START; 13568c2ecf20Sopenharmony_ci rx_status.rate_idx = 0; 13578c2ecf20Sopenharmony_ci rx_status.signal = 50 + 10; 13588c2ecf20Sopenharmony_ci memcpy(IEEE80211_SKB_RXCB(skb_delba), 13598c2ecf20Sopenharmony_ci &rx_status, sizeof(rx_status)); 13608c2ecf20Sopenharmony_ci RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, 13618c2ecf20Sopenharmony_ci "fake del\n", 13628c2ecf20Sopenharmony_ci skb_delba->data, 13638c2ecf20Sopenharmony_ci skb_delba->len); 13648c2ecf20Sopenharmony_ci ieee80211_rx_irqsafe(hw, skb_delba); 13658c2ecf20Sopenharmony_ci } 13668c2ecf20Sopenharmony_ci} 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_cibool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) 13698c2ecf20Sopenharmony_ci{ 13708c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 13718c2ecf20Sopenharmony_ci struct ieee80211_hdr *hdr = rtl_get_hdr(skb); 13728c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 13738c2ecf20Sopenharmony_ci __le16 fc = rtl_get_fc(skb); 13748c2ecf20Sopenharmony_ci u8 *act = (u8 *)(((u8 *)skb->data + MAC80211_3ADDR_LEN)); 13758c2ecf20Sopenharmony_ci u8 category; 13768c2ecf20Sopenharmony_ci 13778c2ecf20Sopenharmony_ci if (!ieee80211_is_action(fc)) 13788c2ecf20Sopenharmony_ci return true; 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci category = *act; 13818c2ecf20Sopenharmony_ci act++; 13828c2ecf20Sopenharmony_ci switch (category) { 13838c2ecf20Sopenharmony_ci case ACT_CAT_BA: 13848c2ecf20Sopenharmony_ci switch (*act) { 13858c2ecf20Sopenharmony_ci case ACT_ADDBAREQ: 13868c2ecf20Sopenharmony_ci if (mac->act_scanning) 13878c2ecf20Sopenharmony_ci return false; 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, 13908c2ecf20Sopenharmony_ci "%s ACT_ADDBAREQ From :%pM\n", 13918c2ecf20Sopenharmony_ci is_tx ? "Tx" : "Rx", hdr->addr2); 13928c2ecf20Sopenharmony_ci RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "req\n", 13938c2ecf20Sopenharmony_ci skb->data, skb->len); 13948c2ecf20Sopenharmony_ci if (!is_tx) { 13958c2ecf20Sopenharmony_ci struct ieee80211_sta *sta = NULL; 13968c2ecf20Sopenharmony_ci struct rtl_sta_info *sta_entry = NULL; 13978c2ecf20Sopenharmony_ci struct rtl_tid_data *tid_data; 13988c2ecf20Sopenharmony_ci struct ieee80211_mgmt *mgmt = (void *)skb->data; 13998c2ecf20Sopenharmony_ci u16 capab = 0, tid = 0; 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci rcu_read_lock(); 14028c2ecf20Sopenharmony_ci sta = rtl_find_sta(hw, hdr->addr3); 14038c2ecf20Sopenharmony_ci if (sta == NULL) { 14048c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEND | COMP_RECV, 14058c2ecf20Sopenharmony_ci DBG_DMESG, "sta is NULL\n"); 14068c2ecf20Sopenharmony_ci rcu_read_unlock(); 14078c2ecf20Sopenharmony_ci return true; 14088c2ecf20Sopenharmony_ci } 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci sta_entry = 14118c2ecf20Sopenharmony_ci (struct rtl_sta_info *)sta->drv_priv; 14128c2ecf20Sopenharmony_ci if (!sta_entry) { 14138c2ecf20Sopenharmony_ci rcu_read_unlock(); 14148c2ecf20Sopenharmony_ci return true; 14158c2ecf20Sopenharmony_ci } 14168c2ecf20Sopenharmony_ci capab = 14178c2ecf20Sopenharmony_ci le16_to_cpu(mgmt->u.action.u.addba_req.capab); 14188c2ecf20Sopenharmony_ci tid = (capab & 14198c2ecf20Sopenharmony_ci IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; 14208c2ecf20Sopenharmony_ci if (tid >= MAX_TID_COUNT) { 14218c2ecf20Sopenharmony_ci rcu_read_unlock(); 14228c2ecf20Sopenharmony_ci return true; 14238c2ecf20Sopenharmony_ci } 14248c2ecf20Sopenharmony_ci tid_data = &sta_entry->tids[tid]; 14258c2ecf20Sopenharmony_ci if (tid_data->agg.rx_agg_state == 14268c2ecf20Sopenharmony_ci RTL_RX_AGG_START) 14278c2ecf20Sopenharmony_ci process_agg_start(hw, hdr, tid); 14288c2ecf20Sopenharmony_ci rcu_read_unlock(); 14298c2ecf20Sopenharmony_ci } 14308c2ecf20Sopenharmony_ci break; 14318c2ecf20Sopenharmony_ci case ACT_ADDBARSP: 14328c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, 14338c2ecf20Sopenharmony_ci "%s ACT_ADDBARSP From :%pM\n", 14348c2ecf20Sopenharmony_ci is_tx ? "Tx" : "Rx", hdr->addr2); 14358c2ecf20Sopenharmony_ci break; 14368c2ecf20Sopenharmony_ci case ACT_DELBA: 14378c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, 14388c2ecf20Sopenharmony_ci "ACT_ADDBADEL From :%pM\n", hdr->addr2); 14398c2ecf20Sopenharmony_ci break; 14408c2ecf20Sopenharmony_ci } 14418c2ecf20Sopenharmony_ci break; 14428c2ecf20Sopenharmony_ci default: 14438c2ecf20Sopenharmony_ci break; 14448c2ecf20Sopenharmony_ci } 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_ci return true; 14478c2ecf20Sopenharmony_ci} 14488c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_action_proc); 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_cistatic void setup_special_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc, 14518c2ecf20Sopenharmony_ci int type) 14528c2ecf20Sopenharmony_ci{ 14538c2ecf20Sopenharmony_ci struct ieee80211_hw *hw = rtlpriv->hw; 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci rtlpriv->ra.is_special_data = true; 14568c2ecf20Sopenharmony_ci if (rtlpriv->cfg->ops->get_btc_status()) 14578c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_ops->btc_special_packet_notify( 14588c2ecf20Sopenharmony_ci rtlpriv, type); 14598c2ecf20Sopenharmony_ci rtl_lps_leave(hw, false); 14608c2ecf20Sopenharmony_ci ppsc->last_delaylps_stamp_jiffies = jiffies; 14618c2ecf20Sopenharmony_ci} 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_cistatic const u8 *rtl_skb_ether_type_ptr(struct ieee80211_hw *hw, 14648c2ecf20Sopenharmony_ci struct sk_buff *skb, bool is_enc) 14658c2ecf20Sopenharmony_ci{ 14668c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 14678c2ecf20Sopenharmony_ci u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb); 14688c2ecf20Sopenharmony_ci u8 encrypt_header_len = 0; 14698c2ecf20Sopenharmony_ci u8 offset; 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci switch (rtlpriv->sec.pairwise_enc_algorithm) { 14728c2ecf20Sopenharmony_ci case WEP40_ENCRYPTION: 14738c2ecf20Sopenharmony_ci case WEP104_ENCRYPTION: 14748c2ecf20Sopenharmony_ci encrypt_header_len = 4;/*WEP_IV_LEN*/ 14758c2ecf20Sopenharmony_ci break; 14768c2ecf20Sopenharmony_ci case TKIP_ENCRYPTION: 14778c2ecf20Sopenharmony_ci encrypt_header_len = 8;/*TKIP_IV_LEN*/ 14788c2ecf20Sopenharmony_ci break; 14798c2ecf20Sopenharmony_ci case AESCCMP_ENCRYPTION: 14808c2ecf20Sopenharmony_ci encrypt_header_len = 8;/*CCMP_HDR_LEN;*/ 14818c2ecf20Sopenharmony_ci break; 14828c2ecf20Sopenharmony_ci default: 14838c2ecf20Sopenharmony_ci break; 14848c2ecf20Sopenharmony_ci } 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci offset = mac_hdr_len + SNAP_SIZE; 14878c2ecf20Sopenharmony_ci if (is_enc) 14888c2ecf20Sopenharmony_ci offset += encrypt_header_len; 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci return skb->data + offset; 14918c2ecf20Sopenharmony_ci} 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci/*should call before software enc*/ 14948c2ecf20Sopenharmony_ciu8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx, 14958c2ecf20Sopenharmony_ci bool is_enc) 14968c2ecf20Sopenharmony_ci{ 14978c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 14988c2ecf20Sopenharmony_ci struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 14998c2ecf20Sopenharmony_ci __le16 fc = rtl_get_fc(skb); 15008c2ecf20Sopenharmony_ci u16 ether_type; 15018c2ecf20Sopenharmony_ci const u8 *ether_type_ptr; 15028c2ecf20Sopenharmony_ci const struct iphdr *ip; 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci if (!ieee80211_is_data(fc)) 15058c2ecf20Sopenharmony_ci goto end; 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci ether_type_ptr = rtl_skb_ether_type_ptr(hw, skb, is_enc); 15088c2ecf20Sopenharmony_ci ether_type = be16_to_cpup((__be16 *)ether_type_ptr); 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci if (ETH_P_IP == ether_type) { 15118c2ecf20Sopenharmony_ci ip = (struct iphdr *)((u8 *)ether_type_ptr + 15128c2ecf20Sopenharmony_ci PROTOC_TYPE_SIZE); 15138c2ecf20Sopenharmony_ci if (IPPROTO_UDP == ip->protocol) { 15148c2ecf20Sopenharmony_ci struct udphdr *udp = (struct udphdr *)((u8 *)ip + 15158c2ecf20Sopenharmony_ci (ip->ihl << 2)); 15168c2ecf20Sopenharmony_ci if (((((u8 *)udp)[1] == 68) && 15178c2ecf20Sopenharmony_ci (((u8 *)udp)[3] == 67)) || 15188c2ecf20Sopenharmony_ci ((((u8 *)udp)[1] == 67) && 15198c2ecf20Sopenharmony_ci (((u8 *)udp)[3] == 68))) { 15208c2ecf20Sopenharmony_ci /* 68 : UDP BOOTP client 15218c2ecf20Sopenharmony_ci * 67 : UDP BOOTP server 15228c2ecf20Sopenharmony_ci */ 15238c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV), 15248c2ecf20Sopenharmony_ci DBG_DMESG, "dhcp %s !!\n", 15258c2ecf20Sopenharmony_ci (is_tx) ? "Tx" : "Rx"); 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci if (is_tx) 15288c2ecf20Sopenharmony_ci setup_special_tx(rtlpriv, ppsc, 15298c2ecf20Sopenharmony_ci PACKET_DHCP); 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci return true; 15328c2ecf20Sopenharmony_ci } 15338c2ecf20Sopenharmony_ci } 15348c2ecf20Sopenharmony_ci } else if (ETH_P_ARP == ether_type) { 15358c2ecf20Sopenharmony_ci if (is_tx) 15368c2ecf20Sopenharmony_ci setup_special_tx(rtlpriv, ppsc, PACKET_ARP); 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_ci return true; 15398c2ecf20Sopenharmony_ci } else if (ETH_P_PAE == ether_type) { 15408c2ecf20Sopenharmony_ci /* EAPOL is seens as in-4way */ 15418c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.in_4way = true; 15428c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.in_4way_ts = jiffies; 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, 15458c2ecf20Sopenharmony_ci "802.1X %s EAPOL pkt!!\n", (is_tx) ? "Tx" : "Rx"); 15468c2ecf20Sopenharmony_ci 15478c2ecf20Sopenharmony_ci if (is_tx) { 15488c2ecf20Sopenharmony_ci rtlpriv->ra.is_special_data = true; 15498c2ecf20Sopenharmony_ci rtl_lps_leave(hw, false); 15508c2ecf20Sopenharmony_ci ppsc->last_delaylps_stamp_jiffies = jiffies; 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_ci setup_special_tx(rtlpriv, ppsc, PACKET_EAPOL); 15538c2ecf20Sopenharmony_ci } 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci return true; 15568c2ecf20Sopenharmony_ci } else if (ETH_P_IPV6 == ether_type) { 15578c2ecf20Sopenharmony_ci /* TODO: Handle any IPv6 cases that need special handling. 15588c2ecf20Sopenharmony_ci * For now, always return false 15598c2ecf20Sopenharmony_ci */ 15608c2ecf20Sopenharmony_ci goto end; 15618c2ecf20Sopenharmony_ci } 15628c2ecf20Sopenharmony_ci 15638c2ecf20Sopenharmony_ciend: 15648c2ecf20Sopenharmony_ci rtlpriv->ra.is_special_data = false; 15658c2ecf20Sopenharmony_ci return false; 15668c2ecf20Sopenharmony_ci} 15678c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_is_special_data); 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_civoid rtl_tx_ackqueue(struct ieee80211_hw *hw, struct sk_buff *skb) 15708c2ecf20Sopenharmony_ci{ 15718c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 15728c2ecf20Sopenharmony_ci struct rtl_tx_report *tx_report = &rtlpriv->tx_report; 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci __skb_queue_tail(&tx_report->queue, skb); 15758c2ecf20Sopenharmony_ci} 15768c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_tx_ackqueue); 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_cistatic void rtl_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, 15798c2ecf20Sopenharmony_ci bool ack) 15808c2ecf20Sopenharmony_ci{ 15818c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 15828c2ecf20Sopenharmony_ci struct ieee80211_tx_info *info; 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci info = IEEE80211_SKB_CB(skb); 15858c2ecf20Sopenharmony_ci ieee80211_tx_info_clear_status(info); 15868c2ecf20Sopenharmony_ci if (ack) { 15878c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_LOUD, 15888c2ecf20Sopenharmony_ci "tx report: ack\n"); 15898c2ecf20Sopenharmony_ci info->flags |= IEEE80211_TX_STAT_ACK; 15908c2ecf20Sopenharmony_ci } else { 15918c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_LOUD, 15928c2ecf20Sopenharmony_ci "tx report: not ack\n"); 15938c2ecf20Sopenharmony_ci info->flags &= ~IEEE80211_TX_STAT_ACK; 15948c2ecf20Sopenharmony_ci } 15958c2ecf20Sopenharmony_ci ieee80211_tx_status_irqsafe(hw, skb); 15968c2ecf20Sopenharmony_ci} 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_cibool rtl_is_tx_report_skb(struct ieee80211_hw *hw, struct sk_buff *skb) 15998c2ecf20Sopenharmony_ci{ 16008c2ecf20Sopenharmony_ci u16 ether_type; 16018c2ecf20Sopenharmony_ci const u8 *ether_type_ptr; 16028c2ecf20Sopenharmony_ci __le16 fc = rtl_get_fc(skb); 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci ether_type_ptr = rtl_skb_ether_type_ptr(hw, skb, true); 16058c2ecf20Sopenharmony_ci ether_type = be16_to_cpup((__be16 *)ether_type_ptr); 16068c2ecf20Sopenharmony_ci 16078c2ecf20Sopenharmony_ci if (ether_type == ETH_P_PAE || ieee80211_is_nullfunc(fc)) 16088c2ecf20Sopenharmony_ci return true; 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_ci return false; 16118c2ecf20Sopenharmony_ci} 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_cistatic u16 rtl_get_tx_report_sn(struct ieee80211_hw *hw, 16148c2ecf20Sopenharmony_ci struct rtlwifi_tx_info *tx_info) 16158c2ecf20Sopenharmony_ci{ 16168c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 16178c2ecf20Sopenharmony_ci struct rtl_tx_report *tx_report = &rtlpriv->tx_report; 16188c2ecf20Sopenharmony_ci u16 sn; 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci /* SW_DEFINE[11:8] are reserved (driver fills zeros) 16218c2ecf20Sopenharmony_ci * SW_DEFINE[7:2] are used by driver 16228c2ecf20Sopenharmony_ci * SW_DEFINE[1:0] are reserved for firmware (driver fills zeros) 16238c2ecf20Sopenharmony_ci */ 16248c2ecf20Sopenharmony_ci sn = (atomic_inc_return(&tx_report->sn) & 0x003F) << 2; 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci tx_report->last_sent_sn = sn; 16278c2ecf20Sopenharmony_ci tx_report->last_sent_time = jiffies; 16288c2ecf20Sopenharmony_ci tx_info->sn = sn; 16298c2ecf20Sopenharmony_ci tx_info->send_time = tx_report->last_sent_time; 16308c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_DMESG, 16318c2ecf20Sopenharmony_ci "Send TX-Report sn=0x%X\n", sn); 16328c2ecf20Sopenharmony_ci 16338c2ecf20Sopenharmony_ci return sn; 16348c2ecf20Sopenharmony_ci} 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_civoid rtl_set_tx_report(struct rtl_tcb_desc *ptcb_desc, u8 *pdesc, 16378c2ecf20Sopenharmony_ci struct ieee80211_hw *hw, struct rtlwifi_tx_info *tx_info) 16388c2ecf20Sopenharmony_ci{ 16398c2ecf20Sopenharmony_ci if (ptcb_desc->use_spe_rpt) { 16408c2ecf20Sopenharmony_ci u16 sn = rtl_get_tx_report_sn(hw, tx_info); 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci SET_TX_DESC_SPE_RPT(pdesc, 1); 16438c2ecf20Sopenharmony_ci SET_TX_DESC_SW_DEFINE(pdesc, sn); 16448c2ecf20Sopenharmony_ci } 16458c2ecf20Sopenharmony_ci} 16468c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_set_tx_report); 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_civoid rtl_tx_report_handler(struct ieee80211_hw *hw, u8 *tmp_buf, u8 c2h_cmd_len) 16498c2ecf20Sopenharmony_ci{ 16508c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 16518c2ecf20Sopenharmony_ci struct rtl_tx_report *tx_report = &rtlpriv->tx_report; 16528c2ecf20Sopenharmony_ci struct rtlwifi_tx_info *tx_info; 16538c2ecf20Sopenharmony_ci struct sk_buff_head *queue = &tx_report->queue; 16548c2ecf20Sopenharmony_ci struct sk_buff *skb; 16558c2ecf20Sopenharmony_ci u16 sn; 16568c2ecf20Sopenharmony_ci u8 st, retry; 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci if (rtlpriv->cfg->spec_ver & RTL_SPEC_EXT_C2H) { 16598c2ecf20Sopenharmony_ci sn = GET_TX_REPORT_SN_V2(tmp_buf); 16608c2ecf20Sopenharmony_ci st = GET_TX_REPORT_ST_V2(tmp_buf); 16618c2ecf20Sopenharmony_ci retry = GET_TX_REPORT_RETRY_V2(tmp_buf); 16628c2ecf20Sopenharmony_ci } else { 16638c2ecf20Sopenharmony_ci sn = GET_TX_REPORT_SN_V1(tmp_buf); 16648c2ecf20Sopenharmony_ci st = GET_TX_REPORT_ST_V1(tmp_buf); 16658c2ecf20Sopenharmony_ci retry = GET_TX_REPORT_RETRY_V1(tmp_buf); 16668c2ecf20Sopenharmony_ci } 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci tx_report->last_recv_sn = sn; 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci skb_queue_walk(queue, skb) { 16718c2ecf20Sopenharmony_ci tx_info = rtl_tx_skb_cb_info(skb); 16728c2ecf20Sopenharmony_ci if (tx_info->sn == sn) { 16738c2ecf20Sopenharmony_ci skb_unlink(skb, queue); 16748c2ecf20Sopenharmony_ci rtl_tx_status(hw, skb, st == 0); 16758c2ecf20Sopenharmony_ci break; 16768c2ecf20Sopenharmony_ci } 16778c2ecf20Sopenharmony_ci } 16788c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_DMESG, 16798c2ecf20Sopenharmony_ci "Recv TX-Report st=0x%02X sn=0x%X retry=0x%X\n", 16808c2ecf20Sopenharmony_ci st, sn, retry); 16818c2ecf20Sopenharmony_ci} 16828c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_tx_report_handler); 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_cibool rtl_check_tx_report_acked(struct ieee80211_hw *hw) 16858c2ecf20Sopenharmony_ci{ 16868c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 16878c2ecf20Sopenharmony_ci struct rtl_tx_report *tx_report = &rtlpriv->tx_report; 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci if (tx_report->last_sent_sn == tx_report->last_recv_sn) 16908c2ecf20Sopenharmony_ci return true; 16918c2ecf20Sopenharmony_ci 16928c2ecf20Sopenharmony_ci if (time_before(tx_report->last_sent_time + 3 * HZ, jiffies)) { 16938c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_WARNING, 16948c2ecf20Sopenharmony_ci "Check TX-Report timeout!! s_sn=0x%X r_sn=0x%X\n", 16958c2ecf20Sopenharmony_ci tx_report->last_sent_sn, tx_report->last_recv_sn); 16968c2ecf20Sopenharmony_ci return true; /* 3 sec. (timeout) seen as acked */ 16978c2ecf20Sopenharmony_ci } 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci return false; 17008c2ecf20Sopenharmony_ci} 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_civoid rtl_wait_tx_report_acked(struct ieee80211_hw *hw, u32 wait_ms) 17038c2ecf20Sopenharmony_ci{ 17048c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 17058c2ecf20Sopenharmony_ci int i; 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci for (i = 0; i < wait_ms; i++) { 17088c2ecf20Sopenharmony_ci if (rtl_check_tx_report_acked(hw)) 17098c2ecf20Sopenharmony_ci break; 17108c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 17118c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, 17128c2ecf20Sopenharmony_ci "Wait 1ms (%d/%d) to disable key.\n", i, wait_ms); 17138c2ecf20Sopenharmony_ci } 17148c2ecf20Sopenharmony_ci} 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ciu32 rtl_get_hal_edca_param(struct ieee80211_hw *hw, 17178c2ecf20Sopenharmony_ci struct ieee80211_vif *vif, 17188c2ecf20Sopenharmony_ci enum wireless_mode wirelessmode, 17198c2ecf20Sopenharmony_ci struct ieee80211_tx_queue_params *param) 17208c2ecf20Sopenharmony_ci{ 17218c2ecf20Sopenharmony_ci u32 reg = 0; 17228c2ecf20Sopenharmony_ci u8 sifstime = 10; 17238c2ecf20Sopenharmony_ci u8 slottime = 20; 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci /* AIFS = AIFSN * slot time + SIFS */ 17268c2ecf20Sopenharmony_ci switch (wirelessmode) { 17278c2ecf20Sopenharmony_ci case WIRELESS_MODE_A: 17288c2ecf20Sopenharmony_ci case WIRELESS_MODE_N_24G: 17298c2ecf20Sopenharmony_ci case WIRELESS_MODE_N_5G: 17308c2ecf20Sopenharmony_ci case WIRELESS_MODE_AC_5G: 17318c2ecf20Sopenharmony_ci case WIRELESS_MODE_AC_24G: 17328c2ecf20Sopenharmony_ci sifstime = 16; 17338c2ecf20Sopenharmony_ci slottime = 9; 17348c2ecf20Sopenharmony_ci break; 17358c2ecf20Sopenharmony_ci case WIRELESS_MODE_G: 17368c2ecf20Sopenharmony_ci slottime = (vif->bss_conf.use_short_slot ? 9 : 20); 17378c2ecf20Sopenharmony_ci break; 17388c2ecf20Sopenharmony_ci default: 17398c2ecf20Sopenharmony_ci break; 17408c2ecf20Sopenharmony_ci } 17418c2ecf20Sopenharmony_ci 17428c2ecf20Sopenharmony_ci reg |= (param->txop & 0x7FF) << 16; 17438c2ecf20Sopenharmony_ci reg |= (fls(param->cw_max) & 0xF) << 12; 17448c2ecf20Sopenharmony_ci reg |= (fls(param->cw_min) & 0xF) << 8; 17458c2ecf20Sopenharmony_ci reg |= (param->aifs & 0x0F) * slottime + sifstime; 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci return reg; 17488c2ecf20Sopenharmony_ci} 17498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_get_hal_edca_param); 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci/********************************************************* 17528c2ecf20Sopenharmony_ci * 17538c2ecf20Sopenharmony_ci * functions called by core.c 17548c2ecf20Sopenharmony_ci * 17558c2ecf20Sopenharmony_ci *********************************************************/ 17568c2ecf20Sopenharmony_ciint rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 17578c2ecf20Sopenharmony_ci struct ieee80211_sta *sta, u16 tid, u16 *ssn) 17588c2ecf20Sopenharmony_ci{ 17598c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 17608c2ecf20Sopenharmony_ci struct rtl_tid_data *tid_data; 17618c2ecf20Sopenharmony_ci struct rtl_sta_info *sta_entry = NULL; 17628c2ecf20Sopenharmony_ci 17638c2ecf20Sopenharmony_ci if (sta == NULL) 17648c2ecf20Sopenharmony_ci return -EINVAL; 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci if (unlikely(tid >= MAX_TID_COUNT)) 17678c2ecf20Sopenharmony_ci return -EINVAL; 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci sta_entry = (struct rtl_sta_info *)sta->drv_priv; 17708c2ecf20Sopenharmony_ci if (!sta_entry) 17718c2ecf20Sopenharmony_ci return -ENXIO; 17728c2ecf20Sopenharmony_ci tid_data = &sta_entry->tids[tid]; 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG, 17758c2ecf20Sopenharmony_ci "on ra = %pM tid = %d seq:%d\n", sta->addr, tid, 17768c2ecf20Sopenharmony_ci *ssn); 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_ci tid_data->agg.agg_state = RTL_AGG_START; 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_ci return IEEE80211_AMPDU_TX_START_IMMEDIATE; 17818c2ecf20Sopenharmony_ci} 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_ciint rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 17848c2ecf20Sopenharmony_ci struct ieee80211_sta *sta, u16 tid) 17858c2ecf20Sopenharmony_ci{ 17868c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 17878c2ecf20Sopenharmony_ci struct rtl_sta_info *sta_entry = NULL; 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_ci if (sta == NULL) 17908c2ecf20Sopenharmony_ci return -EINVAL; 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG, 17938c2ecf20Sopenharmony_ci "on ra = %pM tid = %d\n", sta->addr, tid); 17948c2ecf20Sopenharmony_ci 17958c2ecf20Sopenharmony_ci if (unlikely(tid >= MAX_TID_COUNT)) 17968c2ecf20Sopenharmony_ci return -EINVAL; 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci sta_entry = (struct rtl_sta_info *)sta->drv_priv; 17998c2ecf20Sopenharmony_ci sta_entry->tids[tid].agg.agg_state = RTL_AGG_STOP; 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 18028c2ecf20Sopenharmony_ci return 0; 18038c2ecf20Sopenharmony_ci} 18048c2ecf20Sopenharmony_ci 18058c2ecf20Sopenharmony_ciint rtl_rx_agg_start(struct ieee80211_hw *hw, 18068c2ecf20Sopenharmony_ci struct ieee80211_sta *sta, u16 tid) 18078c2ecf20Sopenharmony_ci{ 18088c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 18098c2ecf20Sopenharmony_ci struct rtl_tid_data *tid_data; 18108c2ecf20Sopenharmony_ci struct rtl_sta_info *sta_entry = NULL; 18118c2ecf20Sopenharmony_ci u8 reject_agg; 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci if (sta == NULL) 18148c2ecf20Sopenharmony_ci return -EINVAL; 18158c2ecf20Sopenharmony_ci 18168c2ecf20Sopenharmony_ci if (unlikely(tid >= MAX_TID_COUNT)) 18178c2ecf20Sopenharmony_ci return -EINVAL; 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_ci if (rtlpriv->cfg->ops->get_btc_status()) { 18208c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_ops->btc_get_ampdu_cfg(rtlpriv, 18218c2ecf20Sopenharmony_ci &reject_agg, 18228c2ecf20Sopenharmony_ci NULL, NULL); 18238c2ecf20Sopenharmony_ci if (reject_agg) 18248c2ecf20Sopenharmony_ci return -EINVAL; 18258c2ecf20Sopenharmony_ci } 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_ci sta_entry = (struct rtl_sta_info *)sta->drv_priv; 18288c2ecf20Sopenharmony_ci if (!sta_entry) 18298c2ecf20Sopenharmony_ci return -ENXIO; 18308c2ecf20Sopenharmony_ci tid_data = &sta_entry->tids[tid]; 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_RECV, DBG_DMESG, 18338c2ecf20Sopenharmony_ci "on ra = %pM tid = %d\n", sta->addr, tid); 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_ci tid_data->agg.rx_agg_state = RTL_RX_AGG_START; 18368c2ecf20Sopenharmony_ci return 0; 18378c2ecf20Sopenharmony_ci} 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ciint rtl_rx_agg_stop(struct ieee80211_hw *hw, 18408c2ecf20Sopenharmony_ci struct ieee80211_sta *sta, u16 tid) 18418c2ecf20Sopenharmony_ci{ 18428c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 18438c2ecf20Sopenharmony_ci struct rtl_sta_info *sta_entry = NULL; 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci if (sta == NULL) 18468c2ecf20Sopenharmony_ci return -EINVAL; 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG, 18498c2ecf20Sopenharmony_ci "on ra = %pM tid = %d\n", sta->addr, tid); 18508c2ecf20Sopenharmony_ci 18518c2ecf20Sopenharmony_ci if (unlikely(tid >= MAX_TID_COUNT)) 18528c2ecf20Sopenharmony_ci return -EINVAL; 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_ci sta_entry = (struct rtl_sta_info *)sta->drv_priv; 18558c2ecf20Sopenharmony_ci sta_entry->tids[tid].agg.rx_agg_state = RTL_RX_AGG_STOP; 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci return 0; 18588c2ecf20Sopenharmony_ci} 18598c2ecf20Sopenharmony_ci 18608c2ecf20Sopenharmony_ciint rtl_tx_agg_oper(struct ieee80211_hw *hw, 18618c2ecf20Sopenharmony_ci struct ieee80211_sta *sta, u16 tid) 18628c2ecf20Sopenharmony_ci{ 18638c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 18648c2ecf20Sopenharmony_ci struct rtl_sta_info *sta_entry = NULL; 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_ci if (sta == NULL) 18678c2ecf20Sopenharmony_ci return -EINVAL; 18688c2ecf20Sopenharmony_ci 18698c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG, 18708c2ecf20Sopenharmony_ci "on ra = %pM tid = %d\n", sta->addr, tid); 18718c2ecf20Sopenharmony_ci 18728c2ecf20Sopenharmony_ci if (unlikely(tid >= MAX_TID_COUNT)) 18738c2ecf20Sopenharmony_ci return -EINVAL; 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_ci sta_entry = (struct rtl_sta_info *)sta->drv_priv; 18768c2ecf20Sopenharmony_ci sta_entry->tids[tid].agg.agg_state = RTL_AGG_OPERATIONAL; 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci return 0; 18798c2ecf20Sopenharmony_ci} 18808c2ecf20Sopenharmony_ci 18818c2ecf20Sopenharmony_civoid rtl_rx_ampdu_apply(struct rtl_priv *rtlpriv) 18828c2ecf20Sopenharmony_ci{ 18838c2ecf20Sopenharmony_ci struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops; 18848c2ecf20Sopenharmony_ci u8 reject_agg = 0, ctrl_agg_size = 0, agg_size = 0; 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci if (rtlpriv->cfg->ops->get_btc_status()) 18878c2ecf20Sopenharmony_ci btc_ops->btc_get_ampdu_cfg(rtlpriv, &reject_agg, 18888c2ecf20Sopenharmony_ci &ctrl_agg_size, &agg_size); 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, 18918c2ecf20Sopenharmony_ci "Set RX AMPDU: coex - reject=%d, ctrl_agg_size=%d, size=%d", 18928c2ecf20Sopenharmony_ci reject_agg, ctrl_agg_size, agg_size); 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_ci rtlpriv->hw->max_rx_aggregation_subframes = 18958c2ecf20Sopenharmony_ci (ctrl_agg_size ? agg_size : IEEE80211_MAX_AMPDU_BUF_HT); 18968c2ecf20Sopenharmony_ci} 18978c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_rx_ampdu_apply); 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_ci/********************************************************* 19008c2ecf20Sopenharmony_ci * 19018c2ecf20Sopenharmony_ci * wq & timer callback functions 19028c2ecf20Sopenharmony_ci * 19038c2ecf20Sopenharmony_ci *********************************************************/ 19048c2ecf20Sopenharmony_ci/* this function is used for roaming */ 19058c2ecf20Sopenharmony_civoid rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb) 19068c2ecf20Sopenharmony_ci{ 19078c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 19088c2ecf20Sopenharmony_ci struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_ci if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) 19118c2ecf20Sopenharmony_ci return; 19128c2ecf20Sopenharmony_ci 19138c2ecf20Sopenharmony_ci if (rtlpriv->mac80211.link_state < MAC80211_LINKED) 19148c2ecf20Sopenharmony_ci return; 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ci /* check if this really is a beacon */ 19178c2ecf20Sopenharmony_ci if (!ieee80211_is_beacon(hdr->frame_control) && 19188c2ecf20Sopenharmony_ci !ieee80211_is_probe_resp(hdr->frame_control)) 19198c2ecf20Sopenharmony_ci return; 19208c2ecf20Sopenharmony_ci 19218c2ecf20Sopenharmony_ci /* min. beacon length + FCS_LEN */ 19228c2ecf20Sopenharmony_ci if (skb->len <= 40 + FCS_LEN) 19238c2ecf20Sopenharmony_ci return; 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci /* and only beacons from the associated BSSID, please */ 19268c2ecf20Sopenharmony_ci if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid)) 19278c2ecf20Sopenharmony_ci return; 19288c2ecf20Sopenharmony_ci 19298c2ecf20Sopenharmony_ci rtlpriv->link_info.bcn_rx_inperiod++; 19308c2ecf20Sopenharmony_ci} 19318c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_beacon_statistic); 19328c2ecf20Sopenharmony_ci 19338c2ecf20Sopenharmony_cistatic void rtl_free_entries_from_scan_list(struct ieee80211_hw *hw) 19348c2ecf20Sopenharmony_ci{ 19358c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 19368c2ecf20Sopenharmony_ci struct rtl_bssid_entry *entry, *next; 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_ci list_for_each_entry_safe(entry, next, &rtlpriv->scan_list.list, list) { 19398c2ecf20Sopenharmony_ci list_del(&entry->list); 19408c2ecf20Sopenharmony_ci kfree(entry); 19418c2ecf20Sopenharmony_ci rtlpriv->scan_list.num--; 19428c2ecf20Sopenharmony_ci } 19438c2ecf20Sopenharmony_ci} 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_cistatic void rtl_free_entries_from_ack_queue(struct ieee80211_hw *hw, 19468c2ecf20Sopenharmony_ci bool chk_timeout) 19478c2ecf20Sopenharmony_ci{ 19488c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 19498c2ecf20Sopenharmony_ci struct rtl_tx_report *tx_report = &rtlpriv->tx_report; 19508c2ecf20Sopenharmony_ci struct sk_buff_head *queue = &tx_report->queue; 19518c2ecf20Sopenharmony_ci struct sk_buff *skb, *tmp; 19528c2ecf20Sopenharmony_ci struct rtlwifi_tx_info *tx_info; 19538c2ecf20Sopenharmony_ci 19548c2ecf20Sopenharmony_ci skb_queue_walk_safe(queue, skb, tmp) { 19558c2ecf20Sopenharmony_ci tx_info = rtl_tx_skb_cb_info(skb); 19568c2ecf20Sopenharmony_ci if (chk_timeout && 19578c2ecf20Sopenharmony_ci time_after(tx_info->send_time + HZ, jiffies)) 19588c2ecf20Sopenharmony_ci continue; 19598c2ecf20Sopenharmony_ci skb_unlink(skb, queue); 19608c2ecf20Sopenharmony_ci rtl_tx_status(hw, skb, false); 19618c2ecf20Sopenharmony_ci } 19628c2ecf20Sopenharmony_ci} 19638c2ecf20Sopenharmony_ci 19648c2ecf20Sopenharmony_civoid rtl_scan_list_expire(struct ieee80211_hw *hw) 19658c2ecf20Sopenharmony_ci{ 19668c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 19678c2ecf20Sopenharmony_ci struct rtl_bssid_entry *entry, *next; 19688c2ecf20Sopenharmony_ci unsigned long flags; 19698c2ecf20Sopenharmony_ci 19708c2ecf20Sopenharmony_ci spin_lock_irqsave(&rtlpriv->locks.scan_list_lock, flags); 19718c2ecf20Sopenharmony_ci 19728c2ecf20Sopenharmony_ci list_for_each_entry_safe(entry, next, &rtlpriv->scan_list.list, list) { 19738c2ecf20Sopenharmony_ci /* 180 seconds */ 19748c2ecf20Sopenharmony_ci if (jiffies_to_msecs(jiffies - entry->age) < 180000) 19758c2ecf20Sopenharmony_ci continue; 19768c2ecf20Sopenharmony_ci 19778c2ecf20Sopenharmony_ci list_del(&entry->list); 19788c2ecf20Sopenharmony_ci rtlpriv->scan_list.num--; 19798c2ecf20Sopenharmony_ci 19808c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SCAN, DBG_LOUD, 19818c2ecf20Sopenharmony_ci "BSSID=%pM is expire in scan list (total=%d)\n", 19828c2ecf20Sopenharmony_ci entry->bssid, rtlpriv->scan_list.num); 19838c2ecf20Sopenharmony_ci kfree(entry); 19848c2ecf20Sopenharmony_ci } 19858c2ecf20Sopenharmony_ci 19868c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rtlpriv->locks.scan_list_lock, flags); 19878c2ecf20Sopenharmony_ci 19888c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.ap_num = rtlpriv->scan_list.num; 19898c2ecf20Sopenharmony_ci} 19908c2ecf20Sopenharmony_ci 19918c2ecf20Sopenharmony_civoid rtl_collect_scan_list(struct ieee80211_hw *hw, struct sk_buff *skb) 19928c2ecf20Sopenharmony_ci{ 19938c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 19948c2ecf20Sopenharmony_ci struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 19958c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 19968c2ecf20Sopenharmony_ci unsigned long flags; 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci struct rtl_bssid_entry *entry; 19998c2ecf20Sopenharmony_ci bool entry_found = false; 20008c2ecf20Sopenharmony_ci 20018c2ecf20Sopenharmony_ci /* check if it is scanning */ 20028c2ecf20Sopenharmony_ci if (!mac->act_scanning) 20038c2ecf20Sopenharmony_ci return; 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_ci /* check if this really is a beacon */ 20068c2ecf20Sopenharmony_ci if (!ieee80211_is_beacon(hdr->frame_control) && 20078c2ecf20Sopenharmony_ci !ieee80211_is_probe_resp(hdr->frame_control)) 20088c2ecf20Sopenharmony_ci return; 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci spin_lock_irqsave(&rtlpriv->locks.scan_list_lock, flags); 20118c2ecf20Sopenharmony_ci 20128c2ecf20Sopenharmony_ci list_for_each_entry(entry, &rtlpriv->scan_list.list, list) { 20138c2ecf20Sopenharmony_ci if (memcmp(entry->bssid, hdr->addr3, ETH_ALEN) == 0) { 20148c2ecf20Sopenharmony_ci list_del_init(&entry->list); 20158c2ecf20Sopenharmony_ci entry_found = true; 20168c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SCAN, DBG_LOUD, 20178c2ecf20Sopenharmony_ci "Update BSSID=%pM to scan list (total=%d)\n", 20188c2ecf20Sopenharmony_ci hdr->addr3, rtlpriv->scan_list.num); 20198c2ecf20Sopenharmony_ci break; 20208c2ecf20Sopenharmony_ci } 20218c2ecf20Sopenharmony_ci } 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci if (!entry_found) { 20248c2ecf20Sopenharmony_ci entry = kmalloc(sizeof(*entry), GFP_ATOMIC); 20258c2ecf20Sopenharmony_ci 20268c2ecf20Sopenharmony_ci if (!entry) 20278c2ecf20Sopenharmony_ci goto label_err; 20288c2ecf20Sopenharmony_ci 20298c2ecf20Sopenharmony_ci memcpy(entry->bssid, hdr->addr3, ETH_ALEN); 20308c2ecf20Sopenharmony_ci rtlpriv->scan_list.num++; 20318c2ecf20Sopenharmony_ci 20328c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_SCAN, DBG_LOUD, 20338c2ecf20Sopenharmony_ci "Add BSSID=%pM to scan list (total=%d)\n", 20348c2ecf20Sopenharmony_ci hdr->addr3, rtlpriv->scan_list.num); 20358c2ecf20Sopenharmony_ci } 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci entry->age = jiffies; 20388c2ecf20Sopenharmony_ci 20398c2ecf20Sopenharmony_ci list_add_tail(&entry->list, &rtlpriv->scan_list.list); 20408c2ecf20Sopenharmony_ci 20418c2ecf20Sopenharmony_cilabel_err: 20428c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rtlpriv->locks.scan_list_lock, flags); 20438c2ecf20Sopenharmony_ci} 20448c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_collect_scan_list); 20458c2ecf20Sopenharmony_ci 20468c2ecf20Sopenharmony_cistatic void rtl_watchdog_wq_callback(struct work_struct *work) 20478c2ecf20Sopenharmony_ci{ 20488c2ecf20Sopenharmony_ci struct rtl_works *rtlworks = container_of(work, struct rtl_works, 20498c2ecf20Sopenharmony_ci watchdog_wq.work); 20508c2ecf20Sopenharmony_ci struct ieee80211_hw *hw = rtlworks->hw; 20518c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 20528c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 20538c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 20548c2ecf20Sopenharmony_ci bool busytraffic = false; 20558c2ecf20Sopenharmony_ci bool tx_busy_traffic = false; 20568c2ecf20Sopenharmony_ci bool rx_busy_traffic = false; 20578c2ecf20Sopenharmony_ci bool higher_busytraffic = false; 20588c2ecf20Sopenharmony_ci bool higher_busyrxtraffic = false; 20598c2ecf20Sopenharmony_ci u8 idx, tid; 20608c2ecf20Sopenharmony_ci u32 rx_cnt_inp4eriod = 0; 20618c2ecf20Sopenharmony_ci u32 tx_cnt_inp4eriod = 0; 20628c2ecf20Sopenharmony_ci u32 aver_rx_cnt_inperiod = 0; 20638c2ecf20Sopenharmony_ci u32 aver_tx_cnt_inperiod = 0; 20648c2ecf20Sopenharmony_ci u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; 20658c2ecf20Sopenharmony_ci u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_ci if (is_hal_stop(rtlhal)) 20688c2ecf20Sopenharmony_ci return; 20698c2ecf20Sopenharmony_ci 20708c2ecf20Sopenharmony_ci /* <1> Determine if action frame is allowed */ 20718c2ecf20Sopenharmony_ci if (mac->link_state > MAC80211_NOLINK) { 20728c2ecf20Sopenharmony_ci if (mac->cnt_after_linked < 20) 20738c2ecf20Sopenharmony_ci mac->cnt_after_linked++; 20748c2ecf20Sopenharmony_ci } else { 20758c2ecf20Sopenharmony_ci mac->cnt_after_linked = 0; 20768c2ecf20Sopenharmony_ci } 20778c2ecf20Sopenharmony_ci 20788c2ecf20Sopenharmony_ci /* <2> to check if traffic busy, if 20798c2ecf20Sopenharmony_ci * busytraffic we don't change channel 20808c2ecf20Sopenharmony_ci */ 20818c2ecf20Sopenharmony_ci if (mac->link_state >= MAC80211_LINKED) { 20828c2ecf20Sopenharmony_ci /* (1) get aver_rx_cnt_inperiod & aver_tx_cnt_inperiod */ 20838c2ecf20Sopenharmony_ci for (idx = 0; idx <= 2; idx++) { 20848c2ecf20Sopenharmony_ci rtlpriv->link_info.num_rx_in4period[idx] = 20858c2ecf20Sopenharmony_ci rtlpriv->link_info.num_rx_in4period[idx + 1]; 20868c2ecf20Sopenharmony_ci rtlpriv->link_info.num_tx_in4period[idx] = 20878c2ecf20Sopenharmony_ci rtlpriv->link_info.num_tx_in4period[idx + 1]; 20888c2ecf20Sopenharmony_ci } 20898c2ecf20Sopenharmony_ci rtlpriv->link_info.num_rx_in4period[3] = 20908c2ecf20Sopenharmony_ci rtlpriv->link_info.num_rx_inperiod; 20918c2ecf20Sopenharmony_ci rtlpriv->link_info.num_tx_in4period[3] = 20928c2ecf20Sopenharmony_ci rtlpriv->link_info.num_tx_inperiod; 20938c2ecf20Sopenharmony_ci for (idx = 0; idx <= 3; idx++) { 20948c2ecf20Sopenharmony_ci rx_cnt_inp4eriod += 20958c2ecf20Sopenharmony_ci rtlpriv->link_info.num_rx_in4period[idx]; 20968c2ecf20Sopenharmony_ci tx_cnt_inp4eriod += 20978c2ecf20Sopenharmony_ci rtlpriv->link_info.num_tx_in4period[idx]; 20988c2ecf20Sopenharmony_ci } 20998c2ecf20Sopenharmony_ci aver_rx_cnt_inperiod = rx_cnt_inp4eriod / 4; 21008c2ecf20Sopenharmony_ci aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4; 21018c2ecf20Sopenharmony_ci 21028c2ecf20Sopenharmony_ci /* (2) check traffic busy */ 21038c2ecf20Sopenharmony_ci if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) { 21048c2ecf20Sopenharmony_ci busytraffic = true; 21058c2ecf20Sopenharmony_ci if (aver_rx_cnt_inperiod > aver_tx_cnt_inperiod) 21068c2ecf20Sopenharmony_ci rx_busy_traffic = true; 21078c2ecf20Sopenharmony_ci else 21088c2ecf20Sopenharmony_ci tx_busy_traffic = false; 21098c2ecf20Sopenharmony_ci } 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci /* Higher Tx/Rx data. */ 21128c2ecf20Sopenharmony_ci if (aver_rx_cnt_inperiod > 4000 || 21138c2ecf20Sopenharmony_ci aver_tx_cnt_inperiod > 4000) { 21148c2ecf20Sopenharmony_ci higher_busytraffic = true; 21158c2ecf20Sopenharmony_ci 21168c2ecf20Sopenharmony_ci /* Extremely high Rx data. */ 21178c2ecf20Sopenharmony_ci if (aver_rx_cnt_inperiod > 5000) 21188c2ecf20Sopenharmony_ci higher_busyrxtraffic = true; 21198c2ecf20Sopenharmony_ci } 21208c2ecf20Sopenharmony_ci 21218c2ecf20Sopenharmony_ci /* check every tid's tx traffic */ 21228c2ecf20Sopenharmony_ci for (tid = 0; tid <= 7; tid++) { 21238c2ecf20Sopenharmony_ci for (idx = 0; idx <= 2; idx++) 21248c2ecf20Sopenharmony_ci rtlpriv->link_info.tidtx_in4period[tid][idx] = 21258c2ecf20Sopenharmony_ci rtlpriv->link_info.tidtx_in4period[tid] 21268c2ecf20Sopenharmony_ci [idx + 1]; 21278c2ecf20Sopenharmony_ci rtlpriv->link_info.tidtx_in4period[tid][3] = 21288c2ecf20Sopenharmony_ci rtlpriv->link_info.tidtx_inperiod[tid]; 21298c2ecf20Sopenharmony_ci 21308c2ecf20Sopenharmony_ci for (idx = 0; idx <= 3; idx++) 21318c2ecf20Sopenharmony_ci tidtx_inp4eriod[tid] += 21328c2ecf20Sopenharmony_ci rtlpriv->link_info.tidtx_in4period[tid][idx]; 21338c2ecf20Sopenharmony_ci aver_tidtx_inperiod[tid] = tidtx_inp4eriod[tid] / 4; 21348c2ecf20Sopenharmony_ci if (aver_tidtx_inperiod[tid] > 5000) 21358c2ecf20Sopenharmony_ci rtlpriv->link_info.higher_busytxtraffic[tid] = 21368c2ecf20Sopenharmony_ci true; 21378c2ecf20Sopenharmony_ci else 21388c2ecf20Sopenharmony_ci rtlpriv->link_info.higher_busytxtraffic[tid] = 21398c2ecf20Sopenharmony_ci false; 21408c2ecf20Sopenharmony_ci } 21418c2ecf20Sopenharmony_ci 21428c2ecf20Sopenharmony_ci /* PS is controlled by coex. */ 21438c2ecf20Sopenharmony_ci if (rtlpriv->cfg->ops->get_btc_status() && 21448c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_ops->btc_is_bt_ctrl_lps(rtlpriv)) 21458c2ecf20Sopenharmony_ci goto label_lps_done; 21468c2ecf20Sopenharmony_ci 21478c2ecf20Sopenharmony_ci if (rtlpriv->link_info.num_rx_inperiod + 21488c2ecf20Sopenharmony_ci rtlpriv->link_info.num_tx_inperiod > 8 || 21498c2ecf20Sopenharmony_ci rtlpriv->link_info.num_rx_inperiod > 2) 21508c2ecf20Sopenharmony_ci rtl_lps_leave(hw, true); 21518c2ecf20Sopenharmony_ci else 21528c2ecf20Sopenharmony_ci rtl_lps_enter(hw, true); 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_cilabel_lps_done: 21558c2ecf20Sopenharmony_ci ; 21568c2ecf20Sopenharmony_ci } 21578c2ecf20Sopenharmony_ci 21588c2ecf20Sopenharmony_ci for (tid = 0; tid <= 7; tid++) 21598c2ecf20Sopenharmony_ci rtlpriv->link_info.tidtx_inperiod[tid] = 0; 21608c2ecf20Sopenharmony_ci 21618c2ecf20Sopenharmony_ci rtlpriv->link_info.busytraffic = busytraffic; 21628c2ecf20Sopenharmony_ci rtlpriv->link_info.higher_busytraffic = higher_busytraffic; 21638c2ecf20Sopenharmony_ci rtlpriv->link_info.rx_busy_traffic = rx_busy_traffic; 21648c2ecf20Sopenharmony_ci rtlpriv->link_info.tx_busy_traffic = tx_busy_traffic; 21658c2ecf20Sopenharmony_ci rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; 21668c2ecf20Sopenharmony_ci 21678c2ecf20Sopenharmony_ci rtlpriv->stats.txbytesunicast_inperiod = 21688c2ecf20Sopenharmony_ci rtlpriv->stats.txbytesunicast - 21698c2ecf20Sopenharmony_ci rtlpriv->stats.txbytesunicast_last; 21708c2ecf20Sopenharmony_ci rtlpriv->stats.rxbytesunicast_inperiod = 21718c2ecf20Sopenharmony_ci rtlpriv->stats.rxbytesunicast - 21728c2ecf20Sopenharmony_ci rtlpriv->stats.rxbytesunicast_last; 21738c2ecf20Sopenharmony_ci rtlpriv->stats.txbytesunicast_last = rtlpriv->stats.txbytesunicast; 21748c2ecf20Sopenharmony_ci rtlpriv->stats.rxbytesunicast_last = rtlpriv->stats.rxbytesunicast; 21758c2ecf20Sopenharmony_ci 21768c2ecf20Sopenharmony_ci rtlpriv->stats.txbytesunicast_inperiod_tp = 21778c2ecf20Sopenharmony_ci (u32)(rtlpriv->stats.txbytesunicast_inperiod * 8 / 2 / 21788c2ecf20Sopenharmony_ci 1024 / 1024); 21798c2ecf20Sopenharmony_ci rtlpriv->stats.rxbytesunicast_inperiod_tp = 21808c2ecf20Sopenharmony_ci (u32)(rtlpriv->stats.rxbytesunicast_inperiod * 8 / 2 / 21818c2ecf20Sopenharmony_ci 1024 / 1024); 21828c2ecf20Sopenharmony_ci 21838c2ecf20Sopenharmony_ci /* <3> DM */ 21848c2ecf20Sopenharmony_ci if (!rtlpriv->cfg->mod_params->disable_watchdog) 21858c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->dm_watchdog(hw); 21868c2ecf20Sopenharmony_ci 21878c2ecf20Sopenharmony_ci /* <4> roaming */ 21888c2ecf20Sopenharmony_ci if (mac->link_state == MAC80211_LINKED && 21898c2ecf20Sopenharmony_ci mac->opmode == NL80211_IFTYPE_STATION) { 21908c2ecf20Sopenharmony_ci if ((rtlpriv->link_info.bcn_rx_inperiod + 21918c2ecf20Sopenharmony_ci rtlpriv->link_info.num_rx_inperiod) == 0) { 21928c2ecf20Sopenharmony_ci rtlpriv->link_info.roam_times++; 21938c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_ERR, DBG_DMESG, 21948c2ecf20Sopenharmony_ci "AP off for %d s\n", 21958c2ecf20Sopenharmony_ci (rtlpriv->link_info.roam_times * 2)); 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci /* if we can't recv beacon for 10s, 21988c2ecf20Sopenharmony_ci * we should reconnect this AP 21998c2ecf20Sopenharmony_ci */ 22008c2ecf20Sopenharmony_ci if (rtlpriv->link_info.roam_times >= 5) { 22018c2ecf20Sopenharmony_ci pr_err("AP off, try to reconnect now\n"); 22028c2ecf20Sopenharmony_ci rtlpriv->link_info.roam_times = 0; 22038c2ecf20Sopenharmony_ci ieee80211_connection_loss( 22048c2ecf20Sopenharmony_ci rtlpriv->mac80211.vif); 22058c2ecf20Sopenharmony_ci } 22068c2ecf20Sopenharmony_ci } else { 22078c2ecf20Sopenharmony_ci rtlpriv->link_info.roam_times = 0; 22088c2ecf20Sopenharmony_ci } 22098c2ecf20Sopenharmony_ci } 22108c2ecf20Sopenharmony_ci 22118c2ecf20Sopenharmony_ci if (rtlpriv->cfg->ops->get_btc_status()) 22128c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_ops->btc_periodical(rtlpriv); 22138c2ecf20Sopenharmony_ci 22148c2ecf20Sopenharmony_ci if (rtlpriv->btcoexist.btc_info.in_4way) { 22158c2ecf20Sopenharmony_ci if (time_after(jiffies, rtlpriv->btcoexist.btc_info.in_4way_ts + 22168c2ecf20Sopenharmony_ci msecs_to_jiffies(IN_4WAY_TIMEOUT_TIME))) 22178c2ecf20Sopenharmony_ci rtlpriv->btcoexist.btc_info.in_4way = false; 22188c2ecf20Sopenharmony_ci } 22198c2ecf20Sopenharmony_ci 22208c2ecf20Sopenharmony_ci rtlpriv->link_info.num_rx_inperiod = 0; 22218c2ecf20Sopenharmony_ci rtlpriv->link_info.num_tx_inperiod = 0; 22228c2ecf20Sopenharmony_ci rtlpriv->link_info.bcn_rx_inperiod = 0; 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci /* <6> scan list */ 22258c2ecf20Sopenharmony_ci rtl_scan_list_expire(hw); 22268c2ecf20Sopenharmony_ci 22278c2ecf20Sopenharmony_ci /* <7> check ack queue */ 22288c2ecf20Sopenharmony_ci rtl_free_entries_from_ack_queue(hw, true); 22298c2ecf20Sopenharmony_ci} 22308c2ecf20Sopenharmony_ci 22318c2ecf20Sopenharmony_civoid rtl_watch_dog_timer_callback(struct timer_list *t) 22328c2ecf20Sopenharmony_ci{ 22338c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = from_timer(rtlpriv, t, works.watchdog_timer); 22348c2ecf20Sopenharmony_ci 22358c2ecf20Sopenharmony_ci queue_delayed_work(rtlpriv->works.rtl_wq, 22368c2ecf20Sopenharmony_ci &rtlpriv->works.watchdog_wq, 0); 22378c2ecf20Sopenharmony_ci 22388c2ecf20Sopenharmony_ci mod_timer(&rtlpriv->works.watchdog_timer, 22398c2ecf20Sopenharmony_ci jiffies + MSECS(RTL_WATCH_DOG_TIME)); 22408c2ecf20Sopenharmony_ci} 22418c2ecf20Sopenharmony_ci 22428c2ecf20Sopenharmony_cistatic void rtl_fwevt_wq_callback(struct work_struct *work) 22438c2ecf20Sopenharmony_ci{ 22448c2ecf20Sopenharmony_ci struct rtl_works *rtlworks = container_of(work, struct rtl_works, 22458c2ecf20Sopenharmony_ci fwevt_wq.work); 22468c2ecf20Sopenharmony_ci struct ieee80211_hw *hw = rtlworks->hw; 22478c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 22488c2ecf20Sopenharmony_ci 22498c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->c2h_command_handle(hw); 22508c2ecf20Sopenharmony_ci} 22518c2ecf20Sopenharmony_ci 22528c2ecf20Sopenharmony_cistatic void rtl_c2h_content_parsing(struct ieee80211_hw *hw, 22538c2ecf20Sopenharmony_ci struct sk_buff *skb); 22548c2ecf20Sopenharmony_ci 22558c2ecf20Sopenharmony_cistatic bool rtl_c2h_fast_cmd(struct ieee80211_hw *hw, struct sk_buff *skb) 22568c2ecf20Sopenharmony_ci{ 22578c2ecf20Sopenharmony_ci u8 cmd_id = GET_C2H_CMD_ID(skb->data); 22588c2ecf20Sopenharmony_ci 22598c2ecf20Sopenharmony_ci switch (cmd_id) { 22608c2ecf20Sopenharmony_ci case C2H_BT_MP: 22618c2ecf20Sopenharmony_ci return true; 22628c2ecf20Sopenharmony_ci default: 22638c2ecf20Sopenharmony_ci break; 22648c2ecf20Sopenharmony_ci } 22658c2ecf20Sopenharmony_ci 22668c2ecf20Sopenharmony_ci return false; 22678c2ecf20Sopenharmony_ci} 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_civoid rtl_c2hcmd_enqueue(struct ieee80211_hw *hw, struct sk_buff *skb) 22708c2ecf20Sopenharmony_ci{ 22718c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 22728c2ecf20Sopenharmony_ci unsigned long flags; 22738c2ecf20Sopenharmony_ci 22748c2ecf20Sopenharmony_ci if (rtl_c2h_fast_cmd(hw, skb)) { 22758c2ecf20Sopenharmony_ci rtl_c2h_content_parsing(hw, skb); 22768c2ecf20Sopenharmony_ci kfree_skb(skb); 22778c2ecf20Sopenharmony_ci return; 22788c2ecf20Sopenharmony_ci } 22798c2ecf20Sopenharmony_ci 22808c2ecf20Sopenharmony_ci /* enqueue */ 22818c2ecf20Sopenharmony_ci spin_lock_irqsave(&rtlpriv->locks.c2hcmd_lock, flags); 22828c2ecf20Sopenharmony_ci 22838c2ecf20Sopenharmony_ci __skb_queue_tail(&rtlpriv->c2hcmd_queue, skb); 22848c2ecf20Sopenharmony_ci 22858c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rtlpriv->locks.c2hcmd_lock, flags); 22868c2ecf20Sopenharmony_ci 22878c2ecf20Sopenharmony_ci /* wake up wq */ 22888c2ecf20Sopenharmony_ci queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.c2hcmd_wq, 0); 22898c2ecf20Sopenharmony_ci} 22908c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_c2hcmd_enqueue); 22918c2ecf20Sopenharmony_ci 22928c2ecf20Sopenharmony_cistatic void rtl_c2h_content_parsing(struct ieee80211_hw *hw, 22938c2ecf20Sopenharmony_ci struct sk_buff *skb) 22948c2ecf20Sopenharmony_ci{ 22958c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 22968c2ecf20Sopenharmony_ci struct rtl_hal_ops *hal_ops = rtlpriv->cfg->ops; 22978c2ecf20Sopenharmony_ci const struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops; 22988c2ecf20Sopenharmony_ci u8 cmd_id, cmd_len; 22998c2ecf20Sopenharmony_ci u8 *cmd_buf = NULL; 23008c2ecf20Sopenharmony_ci 23018c2ecf20Sopenharmony_ci cmd_id = GET_C2H_CMD_ID(skb->data); 23028c2ecf20Sopenharmony_ci cmd_len = skb->len - C2H_DATA_OFFSET; 23038c2ecf20Sopenharmony_ci cmd_buf = GET_C2H_DATA_PTR(skb->data); 23048c2ecf20Sopenharmony_ci 23058c2ecf20Sopenharmony_ci switch (cmd_id) { 23068c2ecf20Sopenharmony_ci case C2H_DBG: 23078c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "[C2H], C2H_DBG!!\n"); 23088c2ecf20Sopenharmony_ci break; 23098c2ecf20Sopenharmony_ci case C2H_TXBF: 23108c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, 23118c2ecf20Sopenharmony_ci "[C2H], C2H_TXBF!!\n"); 23128c2ecf20Sopenharmony_ci break; 23138c2ecf20Sopenharmony_ci case C2H_TX_REPORT: 23148c2ecf20Sopenharmony_ci rtl_tx_report_handler(hw, cmd_buf, cmd_len); 23158c2ecf20Sopenharmony_ci break; 23168c2ecf20Sopenharmony_ci case C2H_RA_RPT: 23178c2ecf20Sopenharmony_ci if (hal_ops->c2h_ra_report_handler) 23188c2ecf20Sopenharmony_ci hal_ops->c2h_ra_report_handler(hw, cmd_buf, cmd_len); 23198c2ecf20Sopenharmony_ci break; 23208c2ecf20Sopenharmony_ci case C2H_BT_INFO: 23218c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, 23228c2ecf20Sopenharmony_ci "[C2H], C2H_BT_INFO!!\n"); 23238c2ecf20Sopenharmony_ci if (rtlpriv->cfg->ops->get_btc_status()) 23248c2ecf20Sopenharmony_ci btc_ops->btc_btinfo_notify(rtlpriv, cmd_buf, cmd_len); 23258c2ecf20Sopenharmony_ci break; 23268c2ecf20Sopenharmony_ci case C2H_BT_MP: 23278c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, 23288c2ecf20Sopenharmony_ci "[C2H], C2H_BT_MP!!\n"); 23298c2ecf20Sopenharmony_ci if (rtlpriv->cfg->ops->get_btc_status()) 23308c2ecf20Sopenharmony_ci btc_ops->btc_btmpinfo_notify(rtlpriv, cmd_buf, cmd_len); 23318c2ecf20Sopenharmony_ci break; 23328c2ecf20Sopenharmony_ci default: 23338c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, 23348c2ecf20Sopenharmony_ci "[C2H], Unknown packet!! cmd_id(%#X)!\n", cmd_id); 23358c2ecf20Sopenharmony_ci break; 23368c2ecf20Sopenharmony_ci } 23378c2ecf20Sopenharmony_ci} 23388c2ecf20Sopenharmony_ci 23398c2ecf20Sopenharmony_civoid rtl_c2hcmd_launcher(struct ieee80211_hw *hw, int exec) 23408c2ecf20Sopenharmony_ci{ 23418c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 23428c2ecf20Sopenharmony_ci struct sk_buff *skb; 23438c2ecf20Sopenharmony_ci unsigned long flags; 23448c2ecf20Sopenharmony_ci int i; 23458c2ecf20Sopenharmony_ci 23468c2ecf20Sopenharmony_ci for (i = 0; i < 200; i++) { 23478c2ecf20Sopenharmony_ci /* dequeue a task */ 23488c2ecf20Sopenharmony_ci spin_lock_irqsave(&rtlpriv->locks.c2hcmd_lock, flags); 23498c2ecf20Sopenharmony_ci 23508c2ecf20Sopenharmony_ci skb = __skb_dequeue(&rtlpriv->c2hcmd_queue); 23518c2ecf20Sopenharmony_ci 23528c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rtlpriv->locks.c2hcmd_lock, flags); 23538c2ecf20Sopenharmony_ci 23548c2ecf20Sopenharmony_ci /* do it */ 23558c2ecf20Sopenharmony_ci if (!skb) 23568c2ecf20Sopenharmony_ci break; 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG, "C2H rx_desc_shift=%d\n", 23598c2ecf20Sopenharmony_ci *((u8 *)skb->cb)); 23608c2ecf20Sopenharmony_ci RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_DMESG, 23618c2ecf20Sopenharmony_ci "C2H data: ", skb->data, skb->len); 23628c2ecf20Sopenharmony_ci 23638c2ecf20Sopenharmony_ci if (exec) 23648c2ecf20Sopenharmony_ci rtl_c2h_content_parsing(hw, skb); 23658c2ecf20Sopenharmony_ci 23668c2ecf20Sopenharmony_ci /* free */ 23678c2ecf20Sopenharmony_ci dev_kfree_skb_any(skb); 23688c2ecf20Sopenharmony_ci } 23698c2ecf20Sopenharmony_ci} 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_cistatic void rtl_c2hcmd_wq_callback(struct work_struct *work) 23728c2ecf20Sopenharmony_ci{ 23738c2ecf20Sopenharmony_ci struct rtl_works *rtlworks = container_of(work, struct rtl_works, 23748c2ecf20Sopenharmony_ci c2hcmd_wq.work); 23758c2ecf20Sopenharmony_ci struct ieee80211_hw *hw = rtlworks->hw; 23768c2ecf20Sopenharmony_ci 23778c2ecf20Sopenharmony_ci rtl_c2hcmd_launcher(hw, 1); 23788c2ecf20Sopenharmony_ci} 23798c2ecf20Sopenharmony_ci 23808c2ecf20Sopenharmony_civoid rtl_easy_concurrent_retrytimer_callback(struct timer_list *t) 23818c2ecf20Sopenharmony_ci{ 23828c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = 23838c2ecf20Sopenharmony_ci from_timer(rtlpriv, t, works.dualmac_easyconcurrent_retrytimer); 23848c2ecf20Sopenharmony_ci struct ieee80211_hw *hw = rtlpriv->hw; 23858c2ecf20Sopenharmony_ci struct rtl_priv *buddy_priv = rtlpriv->buddy_priv; 23868c2ecf20Sopenharmony_ci 23878c2ecf20Sopenharmony_ci if (buddy_priv == NULL) 23888c2ecf20Sopenharmony_ci return; 23898c2ecf20Sopenharmony_ci 23908c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->dualmac_easy_concurrent(hw); 23918c2ecf20Sopenharmony_ci} 23928c2ecf20Sopenharmony_ci 23938c2ecf20Sopenharmony_ci/********************************************************* 23948c2ecf20Sopenharmony_ci * 23958c2ecf20Sopenharmony_ci * frame process functions 23968c2ecf20Sopenharmony_ci * 23978c2ecf20Sopenharmony_ci *********************************************************/ 23988c2ecf20Sopenharmony_ciu8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie) 23998c2ecf20Sopenharmony_ci{ 24008c2ecf20Sopenharmony_ci struct ieee80211_mgmt *mgmt = (void *)data; 24018c2ecf20Sopenharmony_ci u8 *pos, *end; 24028c2ecf20Sopenharmony_ci 24038c2ecf20Sopenharmony_ci pos = (u8 *)mgmt->u.beacon.variable; 24048c2ecf20Sopenharmony_ci end = data + len; 24058c2ecf20Sopenharmony_ci while (pos < end) { 24068c2ecf20Sopenharmony_ci if (pos + 2 + pos[1] > end) 24078c2ecf20Sopenharmony_ci return NULL; 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_ci if (pos[0] == ie) 24108c2ecf20Sopenharmony_ci return pos; 24118c2ecf20Sopenharmony_ci 24128c2ecf20Sopenharmony_ci pos += 2 + pos[1]; 24138c2ecf20Sopenharmony_ci } 24148c2ecf20Sopenharmony_ci return NULL; 24158c2ecf20Sopenharmony_ci} 24168c2ecf20Sopenharmony_ci 24178c2ecf20Sopenharmony_ci/* when we use 2 rx ants we send IEEE80211_SMPS_OFF */ 24188c2ecf20Sopenharmony_ci/* when we use 1 rx ant we send IEEE80211_SMPS_STATIC */ 24198c2ecf20Sopenharmony_cistatic struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw, 24208c2ecf20Sopenharmony_ci enum ieee80211_smps_mode smps, 24218c2ecf20Sopenharmony_ci u8 *da, u8 *bssid) 24228c2ecf20Sopenharmony_ci{ 24238c2ecf20Sopenharmony_ci struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 24248c2ecf20Sopenharmony_ci struct sk_buff *skb; 24258c2ecf20Sopenharmony_ci struct ieee80211_mgmt *action_frame; 24268c2ecf20Sopenharmony_ci 24278c2ecf20Sopenharmony_ci /* 27 = header + category + action + smps mode */ 24288c2ecf20Sopenharmony_ci skb = dev_alloc_skb(27 + hw->extra_tx_headroom); 24298c2ecf20Sopenharmony_ci if (!skb) 24308c2ecf20Sopenharmony_ci return NULL; 24318c2ecf20Sopenharmony_ci 24328c2ecf20Sopenharmony_ci skb_reserve(skb, hw->extra_tx_headroom); 24338c2ecf20Sopenharmony_ci action_frame = skb_put_zero(skb, 27); 24348c2ecf20Sopenharmony_ci memcpy(action_frame->da, da, ETH_ALEN); 24358c2ecf20Sopenharmony_ci memcpy(action_frame->sa, rtlefuse->dev_addr, ETH_ALEN); 24368c2ecf20Sopenharmony_ci memcpy(action_frame->bssid, bssid, ETH_ALEN); 24378c2ecf20Sopenharmony_ci action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 24388c2ecf20Sopenharmony_ci IEEE80211_STYPE_ACTION); 24398c2ecf20Sopenharmony_ci action_frame->u.action.category = WLAN_CATEGORY_HT; 24408c2ecf20Sopenharmony_ci action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS; 24418c2ecf20Sopenharmony_ci switch (smps) { 24428c2ecf20Sopenharmony_ci case IEEE80211_SMPS_AUTOMATIC:/* 0 */ 24438c2ecf20Sopenharmony_ci case IEEE80211_SMPS_NUM_MODES:/* 4 */ 24448c2ecf20Sopenharmony_ci WARN_ON(1); 24458c2ecf20Sopenharmony_ci fallthrough; 24468c2ecf20Sopenharmony_ci case IEEE80211_SMPS_OFF:/* 1 */ /*MIMO_PS_NOLIMIT*/ 24478c2ecf20Sopenharmony_ci action_frame->u.action.u.ht_smps.smps_control = 24488c2ecf20Sopenharmony_ci WLAN_HT_SMPS_CONTROL_DISABLED;/* 0 */ 24498c2ecf20Sopenharmony_ci break; 24508c2ecf20Sopenharmony_ci case IEEE80211_SMPS_STATIC:/* 2 */ /*MIMO_PS_STATIC*/ 24518c2ecf20Sopenharmony_ci action_frame->u.action.u.ht_smps.smps_control = 24528c2ecf20Sopenharmony_ci WLAN_HT_SMPS_CONTROL_STATIC;/* 1 */ 24538c2ecf20Sopenharmony_ci break; 24548c2ecf20Sopenharmony_ci case IEEE80211_SMPS_DYNAMIC:/* 3 */ /*MIMO_PS_DYNAMIC*/ 24558c2ecf20Sopenharmony_ci action_frame->u.action.u.ht_smps.smps_control = 24568c2ecf20Sopenharmony_ci WLAN_HT_SMPS_CONTROL_DYNAMIC;/* 3 */ 24578c2ecf20Sopenharmony_ci break; 24588c2ecf20Sopenharmony_ci } 24598c2ecf20Sopenharmony_ci 24608c2ecf20Sopenharmony_ci return skb; 24618c2ecf20Sopenharmony_ci} 24628c2ecf20Sopenharmony_ci 24638c2ecf20Sopenharmony_ciint rtl_send_smps_action(struct ieee80211_hw *hw, 24648c2ecf20Sopenharmony_ci struct ieee80211_sta *sta, 24658c2ecf20Sopenharmony_ci enum ieee80211_smps_mode smps) 24668c2ecf20Sopenharmony_ci{ 24678c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 24688c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 24698c2ecf20Sopenharmony_ci struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 24708c2ecf20Sopenharmony_ci struct sk_buff *skb = NULL; 24718c2ecf20Sopenharmony_ci struct rtl_tcb_desc tcb_desc; 24728c2ecf20Sopenharmony_ci u8 bssid[ETH_ALEN] = {0}; 24738c2ecf20Sopenharmony_ci 24748c2ecf20Sopenharmony_ci memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); 24758c2ecf20Sopenharmony_ci 24768c2ecf20Sopenharmony_ci if (rtlpriv->mac80211.act_scanning) 24778c2ecf20Sopenharmony_ci goto err_free; 24788c2ecf20Sopenharmony_ci 24798c2ecf20Sopenharmony_ci if (!sta) 24808c2ecf20Sopenharmony_ci goto err_free; 24818c2ecf20Sopenharmony_ci 24828c2ecf20Sopenharmony_ci if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) 24838c2ecf20Sopenharmony_ci goto err_free; 24848c2ecf20Sopenharmony_ci 24858c2ecf20Sopenharmony_ci if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) 24868c2ecf20Sopenharmony_ci goto err_free; 24878c2ecf20Sopenharmony_ci 24888c2ecf20Sopenharmony_ci if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) 24898c2ecf20Sopenharmony_ci memcpy(bssid, rtlpriv->efuse.dev_addr, ETH_ALEN); 24908c2ecf20Sopenharmony_ci else 24918c2ecf20Sopenharmony_ci memcpy(bssid, rtlpriv->mac80211.bssid, ETH_ALEN); 24928c2ecf20Sopenharmony_ci 24938c2ecf20Sopenharmony_ci skb = rtl_make_smps_action(hw, smps, sta->addr, bssid); 24948c2ecf20Sopenharmony_ci /* this is a type = mgmt * stype = action frame */ 24958c2ecf20Sopenharmony_ci if (skb) { 24968c2ecf20Sopenharmony_ci struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 24978c2ecf20Sopenharmony_ci struct rtl_sta_info *sta_entry = 24988c2ecf20Sopenharmony_ci (struct rtl_sta_info *) sta->drv_priv; 24998c2ecf20Sopenharmony_ci sta_entry->mimo_ps = smps; 25008c2ecf20Sopenharmony_ci /* rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0, true); */ 25018c2ecf20Sopenharmony_ci 25028c2ecf20Sopenharmony_ci info->control.rates[0].idx = 0; 25038c2ecf20Sopenharmony_ci info->band = hw->conf.chandef.chan->band; 25048c2ecf20Sopenharmony_ci rtlpriv->intf_ops->adapter_tx(hw, sta, skb, &tcb_desc); 25058c2ecf20Sopenharmony_ci } 25068c2ecf20Sopenharmony_ci return 1; 25078c2ecf20Sopenharmony_ci 25088c2ecf20Sopenharmony_cierr_free: 25098c2ecf20Sopenharmony_ci return 0; 25108c2ecf20Sopenharmony_ci} 25118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_send_smps_action); 25128c2ecf20Sopenharmony_ci 25138c2ecf20Sopenharmony_civoid rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) 25148c2ecf20Sopenharmony_ci{ 25158c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 25168c2ecf20Sopenharmony_ci struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 25178c2ecf20Sopenharmony_ci enum io_type iotype; 25188c2ecf20Sopenharmony_ci 25198c2ecf20Sopenharmony_ci if (!is_hal_stop(rtlhal)) { 25208c2ecf20Sopenharmony_ci switch (operation) { 25218c2ecf20Sopenharmony_ci case SCAN_OPT_BACKUP: 25228c2ecf20Sopenharmony_ci iotype = IO_CMD_PAUSE_DM_BY_SCAN; 25238c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, 25248c2ecf20Sopenharmony_ci HW_VAR_IO_CMD, 25258c2ecf20Sopenharmony_ci (u8 *)&iotype); 25268c2ecf20Sopenharmony_ci break; 25278c2ecf20Sopenharmony_ci case SCAN_OPT_RESTORE: 25288c2ecf20Sopenharmony_ci iotype = IO_CMD_RESUME_DM_BY_SCAN; 25298c2ecf20Sopenharmony_ci rtlpriv->cfg->ops->set_hw_reg(hw, 25308c2ecf20Sopenharmony_ci HW_VAR_IO_CMD, 25318c2ecf20Sopenharmony_ci (u8 *)&iotype); 25328c2ecf20Sopenharmony_ci break; 25338c2ecf20Sopenharmony_ci default: 25348c2ecf20Sopenharmony_ci pr_err("Unknown Scan Backup operation.\n"); 25358c2ecf20Sopenharmony_ci break; 25368c2ecf20Sopenharmony_ci } 25378c2ecf20Sopenharmony_ci } 25388c2ecf20Sopenharmony_ci} 25398c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rtl_phy_scan_operation_backup); 25408c2ecf20Sopenharmony_ci 25418c2ecf20Sopenharmony_ci/* because mac80211 have issues when can receive del ba 25428c2ecf20Sopenharmony_ci * so here we just make a fake del_ba if we receive a ba_req 25438c2ecf20Sopenharmony_ci * but rx_agg was opened to let mac80211 release some ba 25448c2ecf20Sopenharmony_ci * related resources, so please this del_ba for tx 25458c2ecf20Sopenharmony_ci */ 25468c2ecf20Sopenharmony_cistruct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, 25478c2ecf20Sopenharmony_ci u8 *sa, u8 *bssid, u16 tid) 25488c2ecf20Sopenharmony_ci{ 25498c2ecf20Sopenharmony_ci struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 25508c2ecf20Sopenharmony_ci struct sk_buff *skb; 25518c2ecf20Sopenharmony_ci struct ieee80211_mgmt *action_frame; 25528c2ecf20Sopenharmony_ci u16 params; 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_ci /* 27 = header + category + action + smps mode */ 25558c2ecf20Sopenharmony_ci skb = dev_alloc_skb(34 + hw->extra_tx_headroom); 25568c2ecf20Sopenharmony_ci if (!skb) 25578c2ecf20Sopenharmony_ci return NULL; 25588c2ecf20Sopenharmony_ci 25598c2ecf20Sopenharmony_ci skb_reserve(skb, hw->extra_tx_headroom); 25608c2ecf20Sopenharmony_ci action_frame = skb_put_zero(skb, 34); 25618c2ecf20Sopenharmony_ci memcpy(action_frame->sa, sa, ETH_ALEN); 25628c2ecf20Sopenharmony_ci memcpy(action_frame->da, rtlefuse->dev_addr, ETH_ALEN); 25638c2ecf20Sopenharmony_ci memcpy(action_frame->bssid, bssid, ETH_ALEN); 25648c2ecf20Sopenharmony_ci action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 25658c2ecf20Sopenharmony_ci IEEE80211_STYPE_ACTION); 25668c2ecf20Sopenharmony_ci action_frame->u.action.category = WLAN_CATEGORY_BACK; 25678c2ecf20Sopenharmony_ci action_frame->u.action.u.delba.action_code = WLAN_ACTION_DELBA; 25688c2ecf20Sopenharmony_ci params = (u16)(1 << 11); /* bit 11 initiator */ 25698c2ecf20Sopenharmony_ci params |= (u16)(tid << 12); /* bit 15:12 TID number */ 25708c2ecf20Sopenharmony_ci 25718c2ecf20Sopenharmony_ci action_frame->u.action.u.delba.params = cpu_to_le16(params); 25728c2ecf20Sopenharmony_ci action_frame->u.action.u.delba.reason_code = 25738c2ecf20Sopenharmony_ci cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); 25748c2ecf20Sopenharmony_ci 25758c2ecf20Sopenharmony_ci return skb; 25768c2ecf20Sopenharmony_ci} 25778c2ecf20Sopenharmony_ci 25788c2ecf20Sopenharmony_ci/********************************************************* 25798c2ecf20Sopenharmony_ci * 25808c2ecf20Sopenharmony_ci * IOT functions 25818c2ecf20Sopenharmony_ci * 25828c2ecf20Sopenharmony_ci *********************************************************/ 25838c2ecf20Sopenharmony_cistatic bool rtl_chk_vendor_ouisub(struct ieee80211_hw *hw, 25848c2ecf20Sopenharmony_ci struct octet_string vendor_ie) 25858c2ecf20Sopenharmony_ci{ 25868c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 25878c2ecf20Sopenharmony_ci bool matched = false; 25888c2ecf20Sopenharmony_ci static u8 athcap_1[] = { 0x00, 0x03, 0x7F }; 25898c2ecf20Sopenharmony_ci static u8 athcap_2[] = { 0x00, 0x13, 0x74 }; 25908c2ecf20Sopenharmony_ci static u8 broadcap_1[] = { 0x00, 0x10, 0x18 }; 25918c2ecf20Sopenharmony_ci static u8 broadcap_2[] = { 0x00, 0x0a, 0xf7 }; 25928c2ecf20Sopenharmony_ci static u8 broadcap_3[] = { 0x00, 0x05, 0xb5 }; 25938c2ecf20Sopenharmony_ci static u8 racap[] = { 0x00, 0x0c, 0x43 }; 25948c2ecf20Sopenharmony_ci static u8 ciscocap[] = { 0x00, 0x40, 0x96 }; 25958c2ecf20Sopenharmony_ci static u8 marvcap[] = { 0x00, 0x50, 0x43 }; 25968c2ecf20Sopenharmony_ci 25978c2ecf20Sopenharmony_ci if (memcmp(vendor_ie.octet, athcap_1, 3) == 0 || 25988c2ecf20Sopenharmony_ci memcmp(vendor_ie.octet, athcap_2, 3) == 0) { 25998c2ecf20Sopenharmony_ci rtlpriv->mac80211.vendor = PEER_ATH; 26008c2ecf20Sopenharmony_ci matched = true; 26018c2ecf20Sopenharmony_ci } else if (memcmp(vendor_ie.octet, broadcap_1, 3) == 0 || 26028c2ecf20Sopenharmony_ci memcmp(vendor_ie.octet, broadcap_2, 3) == 0 || 26038c2ecf20Sopenharmony_ci memcmp(vendor_ie.octet, broadcap_3, 3) == 0) { 26048c2ecf20Sopenharmony_ci rtlpriv->mac80211.vendor = PEER_BROAD; 26058c2ecf20Sopenharmony_ci matched = true; 26068c2ecf20Sopenharmony_ci } else if (memcmp(vendor_ie.octet, racap, 3) == 0) { 26078c2ecf20Sopenharmony_ci rtlpriv->mac80211.vendor = PEER_RAL; 26088c2ecf20Sopenharmony_ci matched = true; 26098c2ecf20Sopenharmony_ci } else if (memcmp(vendor_ie.octet, ciscocap, 3) == 0) { 26108c2ecf20Sopenharmony_ci rtlpriv->mac80211.vendor = PEER_CISCO; 26118c2ecf20Sopenharmony_ci matched = true; 26128c2ecf20Sopenharmony_ci } else if (memcmp(vendor_ie.octet, marvcap, 3) == 0) { 26138c2ecf20Sopenharmony_ci rtlpriv->mac80211.vendor = PEER_MARV; 26148c2ecf20Sopenharmony_ci matched = true; 26158c2ecf20Sopenharmony_ci } 26168c2ecf20Sopenharmony_ci 26178c2ecf20Sopenharmony_ci return matched; 26188c2ecf20Sopenharmony_ci} 26198c2ecf20Sopenharmony_ci 26208c2ecf20Sopenharmony_cistatic bool rtl_find_221_ie(struct ieee80211_hw *hw, u8 *data, 26218c2ecf20Sopenharmony_ci unsigned int len) 26228c2ecf20Sopenharmony_ci{ 26238c2ecf20Sopenharmony_ci struct ieee80211_mgmt *mgmt = (void *)data; 26248c2ecf20Sopenharmony_ci struct octet_string vendor_ie; 26258c2ecf20Sopenharmony_ci u8 *pos, *end; 26268c2ecf20Sopenharmony_ci 26278c2ecf20Sopenharmony_ci pos = (u8 *)mgmt->u.beacon.variable; 26288c2ecf20Sopenharmony_ci end = data + len; 26298c2ecf20Sopenharmony_ci while (pos < end) { 26308c2ecf20Sopenharmony_ci if (pos[0] == 221) { 26318c2ecf20Sopenharmony_ci vendor_ie.length = pos[1]; 26328c2ecf20Sopenharmony_ci vendor_ie.octet = &pos[2]; 26338c2ecf20Sopenharmony_ci if (rtl_chk_vendor_ouisub(hw, vendor_ie)) 26348c2ecf20Sopenharmony_ci return true; 26358c2ecf20Sopenharmony_ci } 26368c2ecf20Sopenharmony_ci 26378c2ecf20Sopenharmony_ci if (pos + 2 + pos[1] > end) 26388c2ecf20Sopenharmony_ci return false; 26398c2ecf20Sopenharmony_ci 26408c2ecf20Sopenharmony_ci pos += 2 + pos[1]; 26418c2ecf20Sopenharmony_ci } 26428c2ecf20Sopenharmony_ci return false; 26438c2ecf20Sopenharmony_ci} 26448c2ecf20Sopenharmony_ci 26458c2ecf20Sopenharmony_civoid rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len) 26468c2ecf20Sopenharmony_ci{ 26478c2ecf20Sopenharmony_ci struct rtl_priv *rtlpriv = rtl_priv(hw); 26488c2ecf20Sopenharmony_ci struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 26498c2ecf20Sopenharmony_ci struct ieee80211_hdr *hdr = (void *)data; 26508c2ecf20Sopenharmony_ci u32 vendor = PEER_UNKNOWN; 26518c2ecf20Sopenharmony_ci 26528c2ecf20Sopenharmony_ci static u8 ap3_1[3] = { 0x00, 0x14, 0xbf }; 26538c2ecf20Sopenharmony_ci static u8 ap3_2[3] = { 0x00, 0x1a, 0x70 }; 26548c2ecf20Sopenharmony_ci static u8 ap3_3[3] = { 0x00, 0x1d, 0x7e }; 26558c2ecf20Sopenharmony_ci static u8 ap4_1[3] = { 0x00, 0x90, 0xcc }; 26568c2ecf20Sopenharmony_ci static u8 ap4_2[3] = { 0x00, 0x0e, 0x2e }; 26578c2ecf20Sopenharmony_ci static u8 ap4_3[3] = { 0x00, 0x18, 0x02 }; 26588c2ecf20Sopenharmony_ci static u8 ap4_4[3] = { 0x00, 0x17, 0x3f }; 26598c2ecf20Sopenharmony_ci static u8 ap4_5[3] = { 0x00, 0x1c, 0xdf }; 26608c2ecf20Sopenharmony_ci static u8 ap5_1[3] = { 0x00, 0x1c, 0xf0 }; 26618c2ecf20Sopenharmony_ci static u8 ap5_2[3] = { 0x00, 0x21, 0x91 }; 26628c2ecf20Sopenharmony_ci static u8 ap5_3[3] = { 0x00, 0x24, 0x01 }; 26638c2ecf20Sopenharmony_ci static u8 ap5_4[3] = { 0x00, 0x15, 0xe9 }; 26648c2ecf20Sopenharmony_ci static u8 ap5_5[3] = { 0x00, 0x17, 0x9A }; 26658c2ecf20Sopenharmony_ci static u8 ap5_6[3] = { 0x00, 0x18, 0xE7 }; 26668c2ecf20Sopenharmony_ci static u8 ap6_1[3] = { 0x00, 0x17, 0x94 }; 26678c2ecf20Sopenharmony_ci static u8 ap7_1[3] = { 0x00, 0x14, 0xa4 }; 26688c2ecf20Sopenharmony_ci 26698c2ecf20Sopenharmony_ci if (mac->opmode != NL80211_IFTYPE_STATION) 26708c2ecf20Sopenharmony_ci return; 26718c2ecf20Sopenharmony_ci 26728c2ecf20Sopenharmony_ci if (mac->link_state == MAC80211_NOLINK) { 26738c2ecf20Sopenharmony_ci mac->vendor = PEER_UNKNOWN; 26748c2ecf20Sopenharmony_ci return; 26758c2ecf20Sopenharmony_ci } 26768c2ecf20Sopenharmony_ci 26778c2ecf20Sopenharmony_ci if (mac->cnt_after_linked > 2) 26788c2ecf20Sopenharmony_ci return; 26798c2ecf20Sopenharmony_ci 26808c2ecf20Sopenharmony_ci /* check if this really is a beacon */ 26818c2ecf20Sopenharmony_ci if (!ieee80211_is_beacon(hdr->frame_control)) 26828c2ecf20Sopenharmony_ci return; 26838c2ecf20Sopenharmony_ci 26848c2ecf20Sopenharmony_ci /* min. beacon length + FCS_LEN */ 26858c2ecf20Sopenharmony_ci if (len <= 40 + FCS_LEN) 26868c2ecf20Sopenharmony_ci return; 26878c2ecf20Sopenharmony_ci 26888c2ecf20Sopenharmony_ci /* and only beacons from the associated BSSID, please */ 26898c2ecf20Sopenharmony_ci if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid)) 26908c2ecf20Sopenharmony_ci return; 26918c2ecf20Sopenharmony_ci 26928c2ecf20Sopenharmony_ci if (rtl_find_221_ie(hw, data, len)) 26938c2ecf20Sopenharmony_ci vendor = mac->vendor; 26948c2ecf20Sopenharmony_ci 26958c2ecf20Sopenharmony_ci if ((memcmp(mac->bssid, ap5_1, 3) == 0) || 26968c2ecf20Sopenharmony_ci (memcmp(mac->bssid, ap5_2, 3) == 0) || 26978c2ecf20Sopenharmony_ci (memcmp(mac->bssid, ap5_3, 3) == 0) || 26988c2ecf20Sopenharmony_ci (memcmp(mac->bssid, ap5_4, 3) == 0) || 26998c2ecf20Sopenharmony_ci (memcmp(mac->bssid, ap5_5, 3) == 0) || 27008c2ecf20Sopenharmony_ci (memcmp(mac->bssid, ap5_6, 3) == 0) || 27018c2ecf20Sopenharmony_ci vendor == PEER_ATH) { 27028c2ecf20Sopenharmony_ci vendor = PEER_ATH; 27038c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>ath find\n"); 27048c2ecf20Sopenharmony_ci } else if ((memcmp(mac->bssid, ap4_4, 3) == 0) || 27058c2ecf20Sopenharmony_ci (memcmp(mac->bssid, ap4_5, 3) == 0) || 27068c2ecf20Sopenharmony_ci (memcmp(mac->bssid, ap4_1, 3) == 0) || 27078c2ecf20Sopenharmony_ci (memcmp(mac->bssid, ap4_2, 3) == 0) || 27088c2ecf20Sopenharmony_ci (memcmp(mac->bssid, ap4_3, 3) == 0) || 27098c2ecf20Sopenharmony_ci vendor == PEER_RAL) { 27108c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>ral find\n"); 27118c2ecf20Sopenharmony_ci vendor = PEER_RAL; 27128c2ecf20Sopenharmony_ci } else if (memcmp(mac->bssid, ap6_1, 3) == 0 || 27138c2ecf20Sopenharmony_ci vendor == PEER_CISCO) { 27148c2ecf20Sopenharmony_ci vendor = PEER_CISCO; 27158c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>cisco find\n"); 27168c2ecf20Sopenharmony_ci } else if ((memcmp(mac->bssid, ap3_1, 3) == 0) || 27178c2ecf20Sopenharmony_ci (memcmp(mac->bssid, ap3_2, 3) == 0) || 27188c2ecf20Sopenharmony_ci (memcmp(mac->bssid, ap3_3, 3) == 0) || 27198c2ecf20Sopenharmony_ci vendor == PEER_BROAD) { 27208c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>broad find\n"); 27218c2ecf20Sopenharmony_ci vendor = PEER_BROAD; 27228c2ecf20Sopenharmony_ci } else if (memcmp(mac->bssid, ap7_1, 3) == 0 || 27238c2ecf20Sopenharmony_ci vendor == PEER_MARV) { 27248c2ecf20Sopenharmony_ci vendor = PEER_MARV; 27258c2ecf20Sopenharmony_ci rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>marv find\n"); 27268c2ecf20Sopenharmony_ci } 27278c2ecf20Sopenharmony_ci 27288c2ecf20Sopenharmony_ci mac->vendor = vendor; 27298c2ecf20Sopenharmony_ci} 27308c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_recognize_peer); 27318c2ecf20Sopenharmony_ci 27328c2ecf20Sopenharmony_ciMODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>"); 27338c2ecf20Sopenharmony_ciMODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>"); 27348c2ecf20Sopenharmony_ciMODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>"); 27358c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 27368c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); 27378c2ecf20Sopenharmony_ci 27388c2ecf20Sopenharmony_cistruct rtl_global_var rtl_global_var = {}; 27398c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rtl_global_var); 27408c2ecf20Sopenharmony_ci 27418c2ecf20Sopenharmony_cistatic int __init rtl_core_module_init(void) 27428c2ecf20Sopenharmony_ci{ 27438c2ecf20Sopenharmony_ci BUILD_BUG_ON(TX_PWR_BY_RATE_NUM_RATE < TX_PWR_BY_RATE_NUM_SECTION); 27448c2ecf20Sopenharmony_ci BUILD_BUG_ON(MAX_RATE_SECTION_NUM != MAX_RATE_SECTION); 27458c2ecf20Sopenharmony_ci BUILD_BUG_ON(MAX_BASE_NUM_IN_PHY_REG_PG_24G != MAX_RATE_SECTION); 27468c2ecf20Sopenharmony_ci BUILD_BUG_ON(MAX_BASE_NUM_IN_PHY_REG_PG_5G != (MAX_RATE_SECTION - 1)); 27478c2ecf20Sopenharmony_ci 27488c2ecf20Sopenharmony_ci if (rtl_rate_control_register()) 27498c2ecf20Sopenharmony_ci pr_err("rtl: Unable to register rtl_rc, use default RC !!\n"); 27508c2ecf20Sopenharmony_ci 27518c2ecf20Sopenharmony_ci /* add debugfs */ 27528c2ecf20Sopenharmony_ci rtl_debugfs_add_topdir(); 27538c2ecf20Sopenharmony_ci 27548c2ecf20Sopenharmony_ci /* init some global vars */ 27558c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&rtl_global_var.glb_priv_list); 27568c2ecf20Sopenharmony_ci spin_lock_init(&rtl_global_var.glb_list_lock); 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_ci return 0; 27598c2ecf20Sopenharmony_ci} 27608c2ecf20Sopenharmony_ci 27618c2ecf20Sopenharmony_cistatic void __exit rtl_core_module_exit(void) 27628c2ecf20Sopenharmony_ci{ 27638c2ecf20Sopenharmony_ci /*RC*/ 27648c2ecf20Sopenharmony_ci rtl_rate_control_unregister(); 27658c2ecf20Sopenharmony_ci 27668c2ecf20Sopenharmony_ci /* remove debugfs */ 27678c2ecf20Sopenharmony_ci rtl_debugfs_remove_topdir(); 27688c2ecf20Sopenharmony_ci} 27698c2ecf20Sopenharmony_ci 27708c2ecf20Sopenharmony_cimodule_init(rtl_core_module_init); 27718c2ecf20Sopenharmony_cimodule_exit(rtl_core_module_exit); 2772