Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
08aba42
Documentation
arch
block
certs
crypto
drivers
accessibility
acpi
amba
android
ata
atm
auxdisplay
base
bcma
block
bluetooth
bus
cdrom
char
clk
clocksource
connector
cpufreq
cpuidle
crypto
dax
dca
devfreq
dio
dma-buf
dma
edac
eisa
extcon
firewire
firmware
fmc
fpga
gpio
gpu
hid
hsi
hv
hwmon
hwspinlock
hwtracing
i2c
ide
idle
iio
infiniband
input
iommu
ipack
irqchip
isdn
leds
lguest
lightnvm
macintosh
mailbox
mcb
md
media
memory
memstick
message
mfd
misc
mmc
mtd
net
appletalk
arcnet
bonding
caif
can
cris
dsa
ethernet
fddi
fjes
hamradio
hippi
hyperv
ieee802154
ipvlan
irda
phy
plip
ppp
slip
team
usb
vmxnet3
wan
wimax
wireless
admtek
ath
atmel
broadcom
cisco
intel
intersil
marvell
mediatek
ralink
realtek
rtl818x
rtl8xxxu
rtlwifi
btcoexist
rtl8188ee
rtl8192c
rtl8192ce
rtl8192cu
rtl8192de
rtl8192ee
rtl8192se
rtl8723ae
rtl8723be
rtl8723com
rtl8821ae
Kconfig
Makefile
base.c
base.h
cam.c
cam.h
core.c
core.h
debug.c
debug.h
efuse.c
efuse.h
pci.c
pci.h
ps.c
ps.h
pwrseqcmd.h
rc.c
rc.h
regd.c
regd.h
stats.c
stats.h
usb.c
usb.h
wifi.h
Kconfig
Makefile
rsi
st
ti
zydas
Kconfig
Makefile
mac80211_hwsim.c
mac80211_hwsim.h
ray_cs.c
ray_cs.h
rayctl.h
rndis_wlan.c
wl3501.h
wl3501_cs.c
xen-netback
Kconfig
LICENSE.SRC
Makefile
Space.c
dummy.c
eql.c
geneve.c
gtp.c
ifb.c
loopback.c
macsec.c
macvlan.c
macvtap.c
mdio.c
mii.c
netconsole.c
nlmon.c
ntb_netdev.c
rionet.c
sb1000.c
sungem_phy.c
tun.c
veth.c
virtio_net.c
vrf.c
vxlan.c
xen-netfront.c
nfc
ntb
nubus
nvdimm
nvme
nvmem
of
oprofile
parisc
parport
pci
pcmcia
perf
phy
pinctrl
platform
pnp
power
powercap
pps
ps3
ptp
pwm
rapidio
ras
regulator
remoteproc
reset
rpmsg
rtc
s390
sbus
scsi
sfi
sh
sn
soc
spi
spmi
ssb
staging
target
tc
thermal
thunderbolt
tty
uio
usb
uwb
vfio
vhost
video
virt
virtio
vlynq
vme
w1
watchdog
xen
zorro
Kconfig
Makefile
firmware
fs
include
init
ipc
kernel
lib
mm
net
samples
scripts
security
sound
tools
usr
virt
.get_maintainer.ignore
.gitignore
.mailmap
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
REPORTING-BUGS
Breadcrumbs
linux
/
drivers
/
net
/
wireless
/
realtek
/
rtlwifi
/
rc.c
Copy path
Blame
Blame
Latest commit
History
History
307 lines (272 loc) · 8.47 KB
Breadcrumbs
linux
/
drivers
/
net
/
wireless
/
realtek
/
rtlwifi
/
rc.c
Top
File metadata and controls
Code
Blame
307 lines (272 loc) · 8.47 KB
Raw
/****************************************************************************** * * Copyright(c) 2009-2012 Realtek Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * The full GNU General Public License is included in this distribution in the * file called LICENSE. * * Contact Information: * wlanfae <wlanfae@realtek.com> * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, * Hsinchu 300, Taiwan. * * Larry Finger <Larry.Finger@lwfinger.net> * *****************************************************************************/ #include "wifi.h" #include "base.h" #include "rc.h" /* *Finds the highest rate index we can use *if skb is special data like DHCP/EAPOL, we set should *it to lowest rate CCK_1M, otherwise we set rate to *highest rate based on wireless mode used for iwconfig *show Tx rate. */ static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, struct ieee80211_sta *sta, struct sk_buff *skb, bool not_data) { struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_sta_info *sta_entry = NULL; u16 wireless_mode = 0; /* *this rate is no use for true rate, firmware *will control rate at all it just used for *1.show in iwconfig in B/G mode *2.in rtl_get_tcb_desc when we check rate is * 1M we will not use FW rate but user rate. */ if (sta) { sta_entry = (struct rtl_sta_info *)sta->drv_priv; wireless_mode = sta_entry->wireless_mode; } if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true, false) || not_data) { return 0; } else { if (rtlhal->current_bandtype == BAND_ON_2_4G) { if (wireless_mode == WIRELESS_MODE_B) { return B_MODE_MAX_RIX; } else if (wireless_mode == WIRELESS_MODE_G) { return G_MODE_MAX_RIX; } else if (wireless_mode == WIRELESS_MODE_N_24G) { if (get_rf_type(rtlphy) != RF_2T2R) return N_MODE_MCS7_RIX; else return N_MODE_MCS15_RIX; } else if (wireless_mode == WIRELESS_MODE_AC_24G) { return AC_MODE_MCS9_RIX; } return 0; } else { if (wireless_mode == WIRELESS_MODE_A) { return A_MODE_MAX_RIX; } else if (wireless_mode == WIRELESS_MODE_N_5G) { if (get_rf_type(rtlphy) != RF_2T2R) return N_MODE_MCS7_RIX; else return N_MODE_MCS15_RIX; } else if (wireless_mode == WIRELESS_MODE_AC_5G) { return AC_MODE_MCS9_RIX; } return 0; } } } static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv, struct ieee80211_sta *sta, struct ieee80211_tx_rate *rate, struct ieee80211_tx_rate_control *txrc, u8 tries, s8 rix, int rtsctsenable, bool not_data) { struct rtl_mac *mac = rtl_mac(rtlpriv); struct rtl_sta_info *sta_entry = NULL; u16 wireless_mode = 0; u8 sgi_20 = 0, sgi_40 = 0, sgi_80 = 0; if (sta) { sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; sgi_80 = sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80; sta_entry = (struct rtl_sta_info *)sta->drv_priv; wireless_mode = sta_entry->wireless_mode; } rate->count = tries; rate->idx = rix >= 0x00 ? rix : 0x00; if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE && wireless_mode == WIRELESS_MODE_AC_5G) rate->idx += 0x10;/*2NSS for 8812AE*/ if (!not_data) { if (txrc->short_preamble) rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; if (mac->opmode == NL80211_IFTYPE_AP || mac->opmode == NL80211_IFTYPE_ADHOC) { if (sta && (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; if (sta && (sta->vht_cap.vht_supported)) rate->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; } else { if (mac->bw_40) rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; if (mac->bw_80) rate->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; } if (sgi_20 || sgi_40 || sgi_80) rate->flags |= IEEE80211_TX_RC_SHORT_GI; if (sta && sta->ht_cap.ht_supported && ((wireless_mode == WIRELESS_MODE_N_5G) || (wireless_mode == WIRELESS_MODE_N_24G))) rate->flags |= IEEE80211_TX_RC_MCS; if (sta && sta->vht_cap.vht_supported && (wireless_mode == WIRELESS_MODE_AC_5G || wireless_mode == WIRELESS_MODE_AC_24G || wireless_mode == WIRELESS_MODE_AC_ONLY)) rate->flags |= IEEE80211_TX_RC_VHT_MCS; } } static void rtl_get_rate(void *ppriv, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_rate_control *txrc) { struct rtl_priv *rtlpriv = ppriv; struct sk_buff *skb = txrc->skb; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rates = tx_info->control.rates; __le16 fc = rtl_get_fc(skb); u8 try_per_rate, i, rix; bool not_data = !ieee80211_is_data(fc); if (rate_control_send_low(sta, priv_sta, txrc)) return; rix = _rtl_rc_get_highest_rix(rtlpriv, sta, skb, not_data); try_per_rate = 1; _rtl_rc_rate_set_series(rtlpriv, sta, &rates[0], txrc, try_per_rate, rix, 1, not_data); if (!not_data) { for (i = 1; i < 4; i++) _rtl_rc_rate_set_series(rtlpriv, sta, &rates[i], txrc, i, (rix - i), 1, not_data); } } static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, struct rtl_sta_info *sta_entry, u16 tid) { struct rtl_mac *mac = rtl_mac(rtlpriv); if (mac->act_scanning) return false; if (mac->opmode == NL80211_IFTYPE_STATION && mac->cnt_after_linked < 3) return false; if (sta_entry->tids[tid].agg.agg_state == RTL_AGG_STOP) return true; return false; } /*mac80211 Rate Control callbacks*/ static void rtl_tx_status(void *ppriv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { struct rtl_priv *rtlpriv = ppriv; struct rtl_mac *mac = rtl_mac(rtlpriv); struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = rtl_get_fc(skb); struct rtl_sta_info *sta_entry; if (!priv_sta || !ieee80211_is_data(fc)) return; if (rtl_is_special_data(mac->hw, skb, true, true)) return; if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || is_broadcast_ether_addr(ieee80211_get_DA(hdr))) return; if (sta) { /* Check if aggregation has to be enabled for this tid */ sta_entry = (struct rtl_sta_info *) sta->drv_priv; if ((sta->ht_cap.ht_supported) && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { if (ieee80211_is_data_qos(fc)) { u8 tid = rtl_get_tid(skb); if (_rtl_tx_aggr_check(rtlpriv, sta_entry, tid)) { sta_entry->tids[tid].agg.agg_state = RTL_AGG_PROGRESS; ieee80211_start_tx_ba_session(sta, tid, 5000); } } } } } static void rtl_rate_init(void *ppriv, struct ieee80211_supported_band *sband, struct cfg80211_chan_def *chandef, struct ieee80211_sta *sta, void *priv_sta) { } static void rtl_rate_update(void *ppriv, struct ieee80211_supported_band *sband, struct cfg80211_chan_def *chandef, struct ieee80211_sta *sta, void *priv_sta, u32 changed) { } static void *rtl_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) { struct rtl_priv *rtlpriv = rtl_priv(hw); return rtlpriv; } static void rtl_rate_free(void *rtlpriv) { return; } static void *rtl_rate_alloc_sta(void *ppriv, struct ieee80211_sta *sta, gfp_t gfp) { struct rtl_priv *rtlpriv = ppriv; struct rtl_rate_priv *rate_priv; rate_priv = kzalloc(sizeof(struct rtl_rate_priv), gfp); if (!rate_priv) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Unable to allocate private rc structure\n"); return NULL; } rtlpriv->rate_priv = rate_priv; return rate_priv; } static void rtl_rate_free_sta(void *rtlpriv, struct ieee80211_sta *sta, void *priv_sta) { struct rtl_rate_priv *rate_priv = priv_sta; kfree(rate_priv); } static struct rate_control_ops rtl_rate_ops = { .name = "rtl_rc", .alloc = rtl_rate_alloc, .free = rtl_rate_free, .alloc_sta = rtl_rate_alloc_sta, .free_sta = rtl_rate_free_sta, .rate_init = rtl_rate_init, .rate_update = rtl_rate_update, .tx_status = rtl_tx_status, .get_rate = rtl_get_rate, }; int rtl_rate_control_register(void) { return ieee80211_rate_control_register(&rtl_rate_ops); } void rtl_rate_control_unregister(void) { ieee80211_rate_control_unregister(&rtl_rate_ops); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
You can’t perform that action at this time.