2 * Copyright (c) 2014, Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #define COMPUTE_TO (5 * HZ)
22 #define LATEACK_DELAY (10 * HZ)
27 * ath_dynack_get_max_to - set max timeout according to channel width
31 static u32
ath_dynack_get_max_to(struct ath_hw
*ah
)
33 const struct ath9k_channel
*chan
= ah
->curchan
;
38 if (IS_CHAN_HT40(chan
))
40 if (IS_CHAN_HALF_RATE(chan
))
42 if (IS_CHAN_QUARTER_RATE(chan
))
48 * ath_dynack_ewma - EWMA (Exponentially Weighted Moving Average) calculation
50 static inline int ath_dynack_ewma(int old
, int new)
53 return (new * (EWMA_DIV
- EWMA_LEVEL
) +
54 old
* EWMA_LEVEL
) / EWMA_DIV
;
60 * ath_dynack_get_sifs - get sifs time based on phy used
65 static inline u32
ath_dynack_get_sifs(struct ath_hw
*ah
, int phy
)
67 u32 sifs
= CCK_SIFS_TIME
;
69 if (phy
== WLAN_RC_PHY_OFDM
) {
70 if (IS_CHAN_QUARTER_RATE(ah
->curchan
))
71 sifs
= OFDM_SIFS_TIME_QUARTER
;
72 else if (IS_CHAN_HALF_RATE(ah
->curchan
))
73 sifs
= OFDM_SIFS_TIME_HALF
;
75 sifs
= OFDM_SIFS_TIME
;
81 * ath_dynack_bssidmask - filter out ACK frames based on BSSID mask
83 * @mac: receiver address
85 static inline bool ath_dynack_bssidmask(struct ath_hw
*ah
, const u8
*mac
)
88 struct ath_common
*common
= ath9k_hw_common(ah
);
90 for (i
= 0; i
< ETH_ALEN
; i
++) {
91 if ((common
->macaddr
[i
] & common
->bssidmask
[i
]) !=
92 (mac
[i
] & common
->bssidmask
[i
]))
100 * ath_dynack_set_timeout - configure timeouts/slottime registers
105 static void ath_dynack_set_timeout(struct ath_hw
*ah
, int to
)
107 struct ath_common
*common
= ath9k_hw_common(ah
);
108 int slottime
= (to
- 3) / 2;
110 ath_dbg(common
, DYNACK
, "ACK timeout %u slottime %u\n",
112 ath9k_hw_setslottime(ah
, slottime
);
113 ath9k_hw_set_ack_timeout(ah
, to
);
114 ath9k_hw_set_cts_timeout(ah
, to
);
118 * ath_dynack_compute_ackto - compute ACK timeout as the maximum STA timeout
121 * should be called while holding qlock
123 static void ath_dynack_compute_ackto(struct ath_hw
*ah
)
125 struct ath_dynack
*da
= &ah
->dynack
;
129 list_for_each_entry(an
, &da
->nodes
, list
)
133 if (to
&& da
->ackto
!= to
) {
134 ath_dynack_set_timeout(ah
, to
);
140 * ath_dynack_compute_to - compute STA ACK timeout
143 * should be called while holding qlock
145 static void ath_dynack_compute_to(struct ath_hw
*ah
)
147 struct ath_dynack
*da
= &ah
->dynack
;
148 u32 ackto
, ack_ts
, max_to
;
149 struct ieee80211_sta
*sta
;
150 struct ts_info
*st_ts
;
156 max_to
= ath_dynack_get_max_to(ah
);
157 while (da
->st_rbf
.h_rb
!= da
->st_rbf
.t_rb
&&
158 da
->ack_rbf
.h_rb
!= da
->ack_rbf
.t_rb
) {
159 ack_ts
= da
->ack_rbf
.tstamp
[da
->ack_rbf
.h_rb
];
160 st_ts
= &da
->st_rbf
.ts
[da
->st_rbf
.h_rb
];
161 dst
= da
->st_rbf
.addr
[da
->st_rbf
.h_rb
].h_dest
;
162 src
= da
->st_rbf
.addr
[da
->st_rbf
.h_rb
].h_src
;
164 ath_dbg(ath9k_hw_common(ah
), DYNACK
,
165 "ack_ts %u st_ts %u st_dur %u [%u-%u]\n",
166 ack_ts
, st_ts
->tstamp
, st_ts
->dur
,
167 da
->ack_rbf
.h_rb
, da
->st_rbf
.h_rb
);
169 if (ack_ts
> st_ts
->tstamp
+ st_ts
->dur
) {
170 ackto
= ack_ts
- st_ts
->tstamp
- st_ts
->dur
;
172 if (ackto
< max_to
) {
173 sta
= ieee80211_find_sta_by_ifaddr(ah
->hw
, dst
,
176 an
= (struct ath_node
*)sta
->drv_priv
;
177 an
->ackto
= ath_dynack_ewma(an
->ackto
,
179 ath_dbg(ath9k_hw_common(ah
), DYNACK
,
180 "%pM to %d [%u]\n", dst
,
182 if (time_is_before_jiffies(da
->lto
)) {
183 ath_dynack_compute_ackto(ah
);
184 da
->lto
= jiffies
+ COMPUTE_TO
;
187 INCR(da
->ack_rbf
.h_rb
, ATH_DYN_BUF
);
189 INCR(da
->st_rbf
.h_rb
, ATH_DYN_BUF
);
191 INCR(da
->ack_rbf
.h_rb
, ATH_DYN_BUF
);
199 * ath_dynack_sample_tx_ts - status timestamp sampling method
201 * @skb: socket buffer
202 * @ts: tx status info
203 * @sta: station pointer
206 void ath_dynack_sample_tx_ts(struct ath_hw
*ah
, struct sk_buff
*skb
,
207 struct ath_tx_status
*ts
,
208 struct ieee80211_sta
*sta
)
210 struct ieee80211_hdr
*hdr
;
211 struct ath_dynack
*da
= &ah
->dynack
;
212 struct ath_common
*common
= ath9k_hw_common(ah
);
213 struct ieee80211_tx_info
*info
= IEEE80211_SKB_CB(skb
);
214 u32 dur
= ts
->duration
;
217 if (!da
->enabled
|| (info
->flags
& IEEE80211_TX_CTL_NO_ACK
))
220 spin_lock_bh(&da
->qlock
);
222 hdr
= (struct ieee80211_hdr
*)skb
->data
;
225 if (ts
->ts_status
& ATH9K_TXERR_XRETRY
) {
226 if (ieee80211_is_assoc_req(hdr
->frame_control
) ||
227 ieee80211_is_assoc_resp(hdr
->frame_control
) ||
228 ieee80211_is_auth(hdr
->frame_control
)) {
229 u32 max_to
= ath_dynack_get_max_to(ah
);
231 ath_dbg(common
, DYNACK
, "late ack\n");
232 ath_dynack_set_timeout(ah
, max_to
);
236 an
= (struct ath_node
*)sta
->drv_priv
;
239 da
->lto
= jiffies
+ LATEACK_DELAY
;
242 spin_unlock_bh(&da
->qlock
);
246 ridx
= ts
->ts_rateindex
;
248 da
->st_rbf
.ts
[da
->st_rbf
.t_rb
].tstamp
= ts
->ts_tstamp
;
250 /* ether_addr_copy() gives a false warning on gcc-10 so use memcpy()
251 * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97490
253 memcpy(da
->st_rbf
.addr
[da
->st_rbf
.t_rb
].h_dest
, hdr
->addr1
, ETH_ALEN
);
254 memcpy(da
->st_rbf
.addr
[da
->st_rbf
.t_rb
].h_src
, hdr
->addr2
, ETH_ALEN
);
256 if (!(info
->status
.rates
[ridx
].flags
& IEEE80211_TX_RC_MCS
)) {
257 const struct ieee80211_rate
*rate
;
258 struct ieee80211_tx_rate
*rates
= info
->status
.rates
;
261 rate
= &common
->sbands
[info
->band
].bitrates
[rates
[ridx
].idx
];
262 if (info
->band
== NL80211_BAND_2GHZ
&&
263 !(rate
->flags
& IEEE80211_RATE_ERP_G
))
264 phy
= WLAN_RC_PHY_CCK
;
266 phy
= WLAN_RC_PHY_OFDM
;
268 dur
-= ath_dynack_get_sifs(ah
, phy
);
270 da
->st_rbf
.ts
[da
->st_rbf
.t_rb
].dur
= dur
;
272 INCR(da
->st_rbf
.t_rb
, ATH_DYN_BUF
);
273 if (da
->st_rbf
.t_rb
== da
->st_rbf
.h_rb
)
274 INCR(da
->st_rbf
.h_rb
, ATH_DYN_BUF
);
276 ath_dbg(common
, DYNACK
, "{%pM} tx sample %u [dur %u][h %u-t %u]\n",
277 hdr
->addr1
, ts
->ts_tstamp
, dur
, da
->st_rbf
.h_rb
,
280 ath_dynack_compute_to(ah
);
282 spin_unlock_bh(&da
->qlock
);
284 EXPORT_SYMBOL(ath_dynack_sample_tx_ts
);
287 * ath_dynack_sample_ack_ts - ACK timestamp sampling method
289 * @skb: socket buffer
293 void ath_dynack_sample_ack_ts(struct ath_hw
*ah
, struct sk_buff
*skb
,
296 struct ath_dynack
*da
= &ah
->dynack
;
297 struct ath_common
*common
= ath9k_hw_common(ah
);
298 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*)skb
->data
;
300 if (!da
->enabled
|| !ath_dynack_bssidmask(ah
, hdr
->addr1
))
303 spin_lock_bh(&da
->qlock
);
304 da
->ack_rbf
.tstamp
[da
->ack_rbf
.t_rb
] = ts
;
306 INCR(da
->ack_rbf
.t_rb
, ATH_DYN_BUF
);
307 if (da
->ack_rbf
.t_rb
== da
->ack_rbf
.h_rb
)
308 INCR(da
->ack_rbf
.h_rb
, ATH_DYN_BUF
);
310 ath_dbg(common
, DYNACK
, "rx sample %u [h %u-t %u]\n",
311 ts
, da
->ack_rbf
.h_rb
, da
->ack_rbf
.t_rb
);
313 ath_dynack_compute_to(ah
);
315 spin_unlock_bh(&da
->qlock
);
317 EXPORT_SYMBOL(ath_dynack_sample_ack_ts
);
320 * ath_dynack_node_init - init ath_node related info
325 void ath_dynack_node_init(struct ath_hw
*ah
, struct ath_node
*an
)
327 struct ath_dynack
*da
= &ah
->dynack
;
329 an
->ackto
= da
->ackto
;
331 spin_lock_bh(&da
->qlock
);
332 list_add_tail(&an
->list
, &da
->nodes
);
333 spin_unlock_bh(&da
->qlock
);
335 EXPORT_SYMBOL(ath_dynack_node_init
);
338 * ath_dynack_node_deinit - deinit ath_node related info
343 void ath_dynack_node_deinit(struct ath_hw
*ah
, struct ath_node
*an
)
345 struct ath_dynack
*da
= &ah
->dynack
;
347 spin_lock_bh(&da
->qlock
);
349 spin_unlock_bh(&da
->qlock
);
351 EXPORT_SYMBOL(ath_dynack_node_deinit
);
354 * ath_dynack_reset - reset dynack processing
358 void ath_dynack_reset(struct ath_hw
*ah
)
360 struct ath_dynack
*da
= &ah
->dynack
;
363 spin_lock_bh(&da
->qlock
);
365 da
->lto
= jiffies
+ COMPUTE_TO
;
369 da
->ack_rbf
.t_rb
= 0;
370 da
->ack_rbf
.h_rb
= 0;
372 da
->ackto
= ath_dynack_get_max_to(ah
);
373 list_for_each_entry(an
, &da
->nodes
, list
)
374 an
->ackto
= da
->ackto
;
376 /* init acktimeout */
377 ath_dynack_set_timeout(ah
, da
->ackto
);
379 spin_unlock_bh(&da
->qlock
);
381 EXPORT_SYMBOL(ath_dynack_reset
);
384 * ath_dynack_init - init dynack data structure
388 void ath_dynack_init(struct ath_hw
*ah
)
390 struct ath_dynack
*da
= &ah
->dynack
;
392 memset(da
, 0, sizeof(struct ath_dynack
));
394 spin_lock_init(&da
->qlock
);
395 INIT_LIST_HEAD(&da
->nodes
);
396 /* ackto = slottime + sifs + air delay */
397 da
->ackto
= 9 + 16 + 64;
399 ah
->hw
->wiphy
->features
|= NL80211_FEATURE_ACKTO_ESTIMATION
;