1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright(c) 2009-2012 Realtek Corporation.*/ |
3 | |
4 | #include "wifi.h" |
5 | #include "base.h" |
6 | #include "rc.h" |
7 | |
8 | /* |
9 | *Finds the highest rate index we can use |
10 | *if skb is special data like DHCP/EAPOL, we set should |
11 | *it to lowest rate CCK_1M, otherwise we set rate to |
12 | *highest rate based on wireless mode used for iwconfig |
13 | *show Tx rate. |
14 | */ |
15 | static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, |
16 | struct ieee80211_sta *sta, |
17 | struct sk_buff *skb, bool not_data) |
18 | { |
19 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
20 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
21 | struct rtl_sta_info *sta_entry = NULL; |
22 | u16 wireless_mode = 0; |
23 | u8 nss; |
24 | struct ieee80211_tx_rate rate; |
25 | |
26 | switch (get_rf_type(rtlphy)) { |
27 | case RF_4T4R: |
28 | nss = 4; |
29 | break; |
30 | case RF_3T3R: |
31 | nss = 3; |
32 | break; |
33 | case RF_2T2R: |
34 | nss = 2; |
35 | break; |
36 | default: |
37 | nss = 1; |
38 | break; |
39 | } |
40 | |
41 | /* |
42 | *this rate is no use for true rate, firmware |
43 | *will control rate at all it just used for |
44 | *1.show in iwconfig in B/G mode |
45 | *2.in rtl_get_tcb_desc when we check rate is |
46 | * 1M we will not use FW rate but user rate. |
47 | */ |
48 | |
49 | if (sta) { |
50 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; |
51 | wireless_mode = sta_entry->wireless_mode; |
52 | } |
53 | |
54 | if (rtl_is_special_data(hw: rtlpriv->mac80211.hw, skb, is_tx: true, is_enc: false) || |
55 | not_data) { |
56 | return 0; |
57 | } else { |
58 | if (rtlhal->current_bandtype == BAND_ON_2_4G) { |
59 | if (wireless_mode == WIRELESS_MODE_B) { |
60 | return B_MODE_MAX_RIX; |
61 | } else if (wireless_mode == WIRELESS_MODE_G) { |
62 | return G_MODE_MAX_RIX; |
63 | } else if (wireless_mode == WIRELESS_MODE_N_24G) { |
64 | if (nss == 1) |
65 | return N_MODE_MCS7_RIX; |
66 | else |
67 | return N_MODE_MCS15_RIX; |
68 | } else if (wireless_mode == WIRELESS_MODE_AC_24G) { |
69 | if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) { |
70 | ieee80211_rate_set_vht(rate: &rate, |
71 | AC_MODE_MCS8_RIX, |
72 | nss); |
73 | goto out; |
74 | } else { |
75 | ieee80211_rate_set_vht(rate: &rate, |
76 | AC_MODE_MCS9_RIX, |
77 | nss); |
78 | goto out; |
79 | } |
80 | } |
81 | return 0; |
82 | } else { |
83 | if (wireless_mode == WIRELESS_MODE_A) { |
84 | return A_MODE_MAX_RIX; |
85 | } else if (wireless_mode == WIRELESS_MODE_N_5G) { |
86 | if (nss == 1) |
87 | return N_MODE_MCS7_RIX; |
88 | else |
89 | return N_MODE_MCS15_RIX; |
90 | } else if (wireless_mode == WIRELESS_MODE_AC_5G) { |
91 | if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) { |
92 | ieee80211_rate_set_vht(rate: &rate, |
93 | AC_MODE_MCS8_RIX, |
94 | nss); |
95 | goto out; |
96 | } else { |
97 | ieee80211_rate_set_vht(rate: &rate, |
98 | AC_MODE_MCS9_RIX, |
99 | nss); |
100 | goto out; |
101 | } |
102 | } |
103 | return 0; |
104 | } |
105 | } |
106 | |
107 | out: |
108 | return rate.idx; |
109 | } |
110 | |
111 | static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv, |
112 | struct ieee80211_sta *sta, |
113 | struct ieee80211_tx_rate *rate, |
114 | struct ieee80211_tx_rate_control *txrc, |
115 | u8 tries, s8 rix, int rtsctsenable, |
116 | bool not_data) |
117 | { |
118 | struct rtl_mac *mac = rtl_mac(rtlpriv); |
119 | struct rtl_sta_info *sta_entry = NULL; |
120 | u16 wireless_mode = 0; |
121 | u8 sgi_20 = 0, sgi_40 = 0, sgi_80 = 0; |
122 | |
123 | if (sta) { |
124 | sgi_20 = sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20; |
125 | sgi_40 = sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40; |
126 | sgi_80 = sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80; |
127 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; |
128 | wireless_mode = sta_entry->wireless_mode; |
129 | } |
130 | rate->count = tries; |
131 | rate->idx = rix >= 0x00 ? rix : 0x00; |
132 | |
133 | if (!not_data) { |
134 | if (txrc->short_preamble) |
135 | rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; |
136 | if (mac->opmode == NL80211_IFTYPE_AP || |
137 | mac->opmode == NL80211_IFTYPE_ADHOC) { |
138 | if (sta && (sta->deflink.ht_cap.cap & |
139 | IEEE80211_HT_CAP_SUP_WIDTH_20_40)) |
140 | rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; |
141 | if (sta && sta->deflink.vht_cap.vht_supported) |
142 | rate->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; |
143 | } else { |
144 | if (mac->bw_80) |
145 | rate->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; |
146 | else if (mac->bw_40) |
147 | rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; |
148 | } |
149 | |
150 | if (sgi_20 || sgi_40 || sgi_80) |
151 | rate->flags |= IEEE80211_TX_RC_SHORT_GI; |
152 | if (sta && sta->deflink.ht_cap.ht_supported && |
153 | (wireless_mode == WIRELESS_MODE_N_5G || |
154 | wireless_mode == WIRELESS_MODE_N_24G)) |
155 | rate->flags |= IEEE80211_TX_RC_MCS; |
156 | if (sta && sta->deflink.vht_cap.vht_supported && |
157 | (wireless_mode == WIRELESS_MODE_AC_5G || |
158 | wireless_mode == WIRELESS_MODE_AC_24G || |
159 | wireless_mode == WIRELESS_MODE_AC_ONLY)) |
160 | rate->flags |= IEEE80211_TX_RC_VHT_MCS; |
161 | } |
162 | } |
163 | |
164 | static void rtl_get_rate(void *ppriv, struct ieee80211_sta *sta, |
165 | void *priv_sta, |
166 | struct ieee80211_tx_rate_control *txrc) |
167 | { |
168 | struct rtl_priv *rtlpriv = ppriv; |
169 | struct sk_buff *skb = txrc->skb; |
170 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
171 | struct ieee80211_tx_rate *rates = tx_info->control.rates; |
172 | __le16 fc = rtl_get_fc(skb); |
173 | u8 try_per_rate, i, rix; |
174 | bool not_data = !ieee80211_is_data(fc); |
175 | |
176 | rix = _rtl_rc_get_highest_rix(rtlpriv, sta, skb, not_data); |
177 | try_per_rate = 1; |
178 | _rtl_rc_rate_set_series(rtlpriv, sta, rate: &rates[0], txrc, |
179 | tries: try_per_rate, rix, rtsctsenable: 1, not_data); |
180 | |
181 | if (!not_data) { |
182 | for (i = 1; i < 4; i++) |
183 | _rtl_rc_rate_set_series(rtlpriv, sta, rate: &rates[i], |
184 | txrc, tries: i, rix: (rix - i), rtsctsenable: 1, |
185 | not_data); |
186 | } |
187 | } |
188 | |
189 | static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, |
190 | struct rtl_sta_info *sta_entry, u16 tid) |
191 | { |
192 | struct rtl_mac *mac = rtl_mac(rtlpriv); |
193 | |
194 | if (mac->act_scanning) |
195 | return false; |
196 | |
197 | if (mac->opmode == NL80211_IFTYPE_STATION && |
198 | mac->cnt_after_linked < 3) |
199 | return false; |
200 | |
201 | if (sta_entry->tids[tid].agg.agg_state == RTL_AGG_STOP) |
202 | return true; |
203 | |
204 | return false; |
205 | } |
206 | |
207 | /*mac80211 Rate Control callbacks*/ |
208 | static void rtl_tx_status(void *ppriv, |
209 | struct ieee80211_supported_band *sband, |
210 | struct ieee80211_sta *sta, void *priv_sta, |
211 | struct sk_buff *skb) |
212 | { |
213 | struct rtl_priv *rtlpriv = ppriv; |
214 | struct rtl_mac *mac = rtl_mac(rtlpriv); |
215 | struct ieee80211_hdr *hdr = rtl_get_hdr(skb); |
216 | __le16 fc = rtl_get_fc(skb); |
217 | struct rtl_sta_info *sta_entry; |
218 | |
219 | if (!priv_sta || !ieee80211_is_data(fc)) |
220 | return; |
221 | |
222 | if (rtl_is_special_data(hw: mac->hw, skb, is_tx: true, is_enc: true)) |
223 | return; |
224 | |
225 | if (is_multicast_ether_addr(addr: ieee80211_get_DA(hdr)) || |
226 | is_broadcast_ether_addr(addr: ieee80211_get_DA(hdr))) |
227 | return; |
228 | |
229 | if (sta) { |
230 | /* Check if aggregation has to be enabled for this tid */ |
231 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; |
232 | if (sta->deflink.ht_cap.ht_supported && |
233 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { |
234 | if (ieee80211_is_data_qos(fc)) { |
235 | u8 tid = rtl_get_tid(skb); |
236 | |
237 | if (_rtl_tx_aggr_check(rtlpriv, sta_entry, |
238 | tid)) { |
239 | sta_entry->tids[tid].agg.agg_state = |
240 | RTL_AGG_PROGRESS; |
241 | ieee80211_start_tx_ba_session(sta, tid, |
242 | timeout: 5000); |
243 | } |
244 | } |
245 | } |
246 | } |
247 | } |
248 | |
249 | static void rtl_rate_init(void *ppriv, |
250 | struct ieee80211_supported_band *sband, |
251 | struct cfg80211_chan_def *chandef, |
252 | struct ieee80211_sta *sta, void *priv_sta) |
253 | { |
254 | } |
255 | |
256 | static void rtl_rate_update(void *ppriv, |
257 | struct ieee80211_supported_band *sband, |
258 | struct cfg80211_chan_def *chandef, |
259 | struct ieee80211_sta *sta, void *priv_sta, |
260 | u32 changed) |
261 | { |
262 | } |
263 | |
264 | static void *rtl_rate_alloc(struct ieee80211_hw *hw) |
265 | { |
266 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
267 | return rtlpriv; |
268 | } |
269 | |
270 | static void rtl_rate_free(void *rtlpriv) |
271 | { |
272 | return; |
273 | } |
274 | |
275 | static void *rtl_rate_alloc_sta(void *ppriv, |
276 | struct ieee80211_sta *sta, gfp_t gfp) |
277 | { |
278 | struct rtl_priv *rtlpriv = ppriv; |
279 | struct rtl_rate_priv *rate_priv; |
280 | |
281 | rate_priv = kzalloc(size: sizeof(*rate_priv), flags: gfp); |
282 | if (!rate_priv) |
283 | return NULL; |
284 | |
285 | rtlpriv->rate_priv = rate_priv; |
286 | |
287 | return rate_priv; |
288 | } |
289 | |
290 | static void rtl_rate_free_sta(void *rtlpriv, |
291 | struct ieee80211_sta *sta, void *priv_sta) |
292 | { |
293 | struct rtl_rate_priv *rate_priv = priv_sta; |
294 | |
295 | kfree(objp: rate_priv); |
296 | } |
297 | |
298 | static const struct rate_control_ops rtl_rate_ops = { |
299 | .name = "rtl_rc" , |
300 | .alloc = rtl_rate_alloc, |
301 | .free = rtl_rate_free, |
302 | .alloc_sta = rtl_rate_alloc_sta, |
303 | .free_sta = rtl_rate_free_sta, |
304 | .rate_init = rtl_rate_init, |
305 | .rate_update = rtl_rate_update, |
306 | .tx_status = rtl_tx_status, |
307 | .get_rate = rtl_get_rate, |
308 | }; |
309 | |
310 | int rtl_rate_control_register(void) |
311 | { |
312 | return ieee80211_rate_control_register(ops: &rtl_rate_ops); |
313 | } |
314 | |
315 | void rtl_rate_control_unregister(void) |
316 | { |
317 | ieee80211_rate_control_unregister(ops: &rtl_rate_ops); |
318 | } |
319 | |