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)
23 #define LATEACK_TO 256
29 * ath_dynack_ewma - EWMA (Exponentially Weighted Moving Average) calculation
32 static inline int ath_dynack_ewma(int old
, int new)
35 return (new * (EWMA_DIV
- EWMA_LEVEL
) +
36 old
* EWMA_LEVEL
) / EWMA_DIV
;
42 * ath_dynack_get_sifs - get sifs time based on phy used
47 static inline u32
ath_dynack_get_sifs(struct ath_hw
*ah
, int phy
)
49 u32 sifs
= CCK_SIFS_TIME
;
51 if (phy
== WLAN_RC_PHY_OFDM
) {
52 if (IS_CHAN_QUARTER_RATE(ah
->curchan
))
53 sifs
= OFDM_SIFS_TIME_QUARTER
;
54 else if (IS_CHAN_HALF_RATE(ah
->curchan
))
55 sifs
= OFDM_SIFS_TIME_HALF
;
57 sifs
= OFDM_SIFS_TIME
;
63 * ath_dynack_bssidmask - filter out ACK frames based on BSSID mask
65 * @mac: receiver address
67 static inline bool ath_dynack_bssidmask(struct ath_hw
*ah
, const u8
*mac
)
70 struct ath_common
*common
= ath9k_hw_common(ah
);
72 for (i
= 0; i
< ETH_ALEN
; i
++) {
73 if ((common
->macaddr
[i
] & common
->bssidmask
[i
]) !=
74 (mac
[i
] & common
->bssidmask
[i
]))
82 * ath_dynack_compute_ackto - compute ACK timeout as the maximum STA timeout
85 * should be called while holding qlock
87 static void ath_dynack_compute_ackto(struct ath_hw
*ah
)
89 struct ath_common
*common
= ath9k_hw_common(ah
);
90 struct ath_dynack
*da
= &ah
->dynack
;
94 list_for_each_entry(an
, &da
->nodes
, list
)
98 if (to
&& da
->ackto
!= to
) {
101 slottime
= (to
- 3) / 2;
103 ath_dbg(common
, DYNACK
, "ACK timeout %u slottime %u\n",
104 da
->ackto
, slottime
);
105 ath9k_hw_setslottime(ah
, slottime
);
106 ath9k_hw_set_ack_timeout(ah
, da
->ackto
);
107 ath9k_hw_set_cts_timeout(ah
, da
->ackto
);
112 * ath_dynack_compute_to - compute STA ACK timeout
115 * should be called while holding qlock
117 static void ath_dynack_compute_to(struct ath_hw
*ah
)
121 struct ieee80211_sta
*sta
;
123 struct ts_info
*st_ts
;
124 struct ath_dynack
*da
= &ah
->dynack
;
128 while (da
->st_rbf
.h_rb
!= da
->st_rbf
.t_rb
&&
129 da
->ack_rbf
.h_rb
!= da
->ack_rbf
.t_rb
) {
130 ack_ts
= da
->ack_rbf
.tstamp
[da
->ack_rbf
.h_rb
];
131 st_ts
= &da
->st_rbf
.ts
[da
->st_rbf
.h_rb
];
132 dst
= da
->st_rbf
.addr
[da
->st_rbf
.h_rb
].h_dest
;
133 src
= da
->st_rbf
.addr
[da
->st_rbf
.h_rb
].h_src
;
135 ath_dbg(ath9k_hw_common(ah
), DYNACK
,
136 "ack_ts %u st_ts %u st_dur %u [%u-%u]\n",
137 ack_ts
, st_ts
->tstamp
, st_ts
->dur
,
138 da
->ack_rbf
.h_rb
, da
->st_rbf
.h_rb
);
140 if (ack_ts
> st_ts
->tstamp
+ st_ts
->dur
) {
141 ackto
= ack_ts
- st_ts
->tstamp
- st_ts
->dur
;
143 if (ackto
< MAX_DELAY
) {
144 sta
= ieee80211_find_sta_by_ifaddr(ah
->hw
, dst
,
147 an
= (struct ath_node
*)sta
->drv_priv
;
148 an
->ackto
= ath_dynack_ewma(an
->ackto
,
150 ath_dbg(ath9k_hw_common(ah
), DYNACK
,
151 "%pM to %d [%u]\n", dst
,
153 if (time_is_before_jiffies(da
->lto
)) {
154 ath_dynack_compute_ackto(ah
);
155 da
->lto
= jiffies
+ COMPUTE_TO
;
158 INCR(da
->ack_rbf
.h_rb
, ATH_DYN_BUF
);
160 INCR(da
->st_rbf
.h_rb
, ATH_DYN_BUF
);
162 INCR(da
->ack_rbf
.h_rb
, ATH_DYN_BUF
);
170 * ath_dynack_sample_tx_ts - status timestamp sampling method
172 * @skb: socket buffer
173 * @ts: tx status info
174 * @sta: station pointer
177 void ath_dynack_sample_tx_ts(struct ath_hw
*ah
, struct sk_buff
*skb
,
178 struct ath_tx_status
*ts
,
179 struct ieee80211_sta
*sta
)
181 struct ieee80211_hdr
*hdr
;
182 struct ath_dynack
*da
= &ah
->dynack
;
183 struct ath_common
*common
= ath9k_hw_common(ah
);
184 struct ieee80211_tx_info
*info
= IEEE80211_SKB_CB(skb
);
185 u32 dur
= ts
->duration
;
188 if (!da
->enabled
|| (info
->flags
& IEEE80211_TX_CTL_NO_ACK
))
191 spin_lock_bh(&da
->qlock
);
193 hdr
= (struct ieee80211_hdr
*)skb
->data
;
196 if (ts
->ts_status
& ATH9K_TXERR_XRETRY
) {
197 if (ieee80211_is_assoc_req(hdr
->frame_control
) ||
198 ieee80211_is_assoc_resp(hdr
->frame_control
) ||
199 ieee80211_is_auth(hdr
->frame_control
)) {
200 ath_dbg(common
, DYNACK
, "late ack\n");
202 ath9k_hw_setslottime(ah
, (LATEACK_TO
- 3) / 2);
203 ath9k_hw_set_ack_timeout(ah
, LATEACK_TO
);
204 ath9k_hw_set_cts_timeout(ah
, LATEACK_TO
);
208 an
= (struct ath_node
*)sta
->drv_priv
;
211 da
->lto
= jiffies
+ LATEACK_DELAY
;
214 spin_unlock_bh(&da
->qlock
);
218 ridx
= ts
->ts_rateindex
;
220 da
->st_rbf
.ts
[da
->st_rbf
.t_rb
].tstamp
= ts
->ts_tstamp
;
221 ether_addr_copy(da
->st_rbf
.addr
[da
->st_rbf
.t_rb
].h_dest
, hdr
->addr1
);
222 ether_addr_copy(da
->st_rbf
.addr
[da
->st_rbf
.t_rb
].h_src
, hdr
->addr2
);
224 if (!(info
->status
.rates
[ridx
].flags
& IEEE80211_TX_RC_MCS
)) {
225 const struct ieee80211_rate
*rate
;
226 struct ieee80211_tx_rate
*rates
= info
->status
.rates
;
229 rate
= &common
->sbands
[info
->band
].bitrates
[rates
[ridx
].idx
];
230 if (info
->band
== NL80211_BAND_2GHZ
&&
231 !(rate
->flags
& IEEE80211_RATE_ERP_G
))
232 phy
= WLAN_RC_PHY_CCK
;
234 phy
= WLAN_RC_PHY_OFDM
;
236 dur
-= ath_dynack_get_sifs(ah
, phy
);
238 da
->st_rbf
.ts
[da
->st_rbf
.t_rb
].dur
= dur
;
240 INCR(da
->st_rbf
.t_rb
, ATH_DYN_BUF
);
241 if (da
->st_rbf
.t_rb
== da
->st_rbf
.h_rb
)
242 INCR(da
->st_rbf
.h_rb
, ATH_DYN_BUF
);
244 ath_dbg(common
, DYNACK
, "{%pM} tx sample %u [dur %u][h %u-t %u]\n",
245 hdr
->addr1
, ts
->ts_tstamp
, dur
, da
->st_rbf
.h_rb
,
248 ath_dynack_compute_to(ah
);
250 spin_unlock_bh(&da
->qlock
);
252 EXPORT_SYMBOL(ath_dynack_sample_tx_ts
);
255 * ath_dynack_sample_ack_ts - ACK timestamp sampling method
257 * @skb: socket buffer
261 void ath_dynack_sample_ack_ts(struct ath_hw
*ah
, struct sk_buff
*skb
,
264 struct ath_dynack
*da
= &ah
->dynack
;
265 struct ath_common
*common
= ath9k_hw_common(ah
);
266 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*)skb
->data
;
268 if (!da
->enabled
|| !ath_dynack_bssidmask(ah
, hdr
->addr1
))
271 spin_lock_bh(&da
->qlock
);
272 da
->ack_rbf
.tstamp
[da
->ack_rbf
.t_rb
] = ts
;
274 INCR(da
->ack_rbf
.t_rb
, ATH_DYN_BUF
);
275 if (da
->ack_rbf
.t_rb
== da
->ack_rbf
.h_rb
)
276 INCR(da
->ack_rbf
.h_rb
, ATH_DYN_BUF
);
278 ath_dbg(common
, DYNACK
, "rx sample %u [h %u-t %u]\n",
279 ts
, da
->ack_rbf
.h_rb
, da
->ack_rbf
.t_rb
);
281 ath_dynack_compute_to(ah
);
283 spin_unlock_bh(&da
->qlock
);
285 EXPORT_SYMBOL(ath_dynack_sample_ack_ts
);
288 * ath_dynack_node_init - init ath_node related info
293 void ath_dynack_node_init(struct ath_hw
*ah
, struct ath_node
*an
)
295 /* ackto = slottime + sifs + air delay */
296 u32 ackto
= 9 + 16 + 64;
297 struct ath_dynack
*da
= &ah
->dynack
;
301 spin_lock(&da
->qlock
);
302 list_add_tail(&an
->list
, &da
->nodes
);
303 spin_unlock(&da
->qlock
);
305 EXPORT_SYMBOL(ath_dynack_node_init
);
308 * ath_dynack_node_deinit - deinit ath_node related info
313 void ath_dynack_node_deinit(struct ath_hw
*ah
, struct ath_node
*an
)
315 struct ath_dynack
*da
= &ah
->dynack
;
317 spin_lock(&da
->qlock
);
319 spin_unlock(&da
->qlock
);
321 EXPORT_SYMBOL(ath_dynack_node_deinit
);
324 * ath_dynack_reset - reset dynack processing
328 void ath_dynack_reset(struct ath_hw
*ah
)
330 /* ackto = slottime + sifs + air delay */
331 u32 ackto
= 9 + 16 + 64;
332 struct ath_dynack
*da
= &ah
->dynack
;
339 da
->ack_rbf
.t_rb
= 0;
340 da
->ack_rbf
.h_rb
= 0;
342 /* init acktimeout */
343 ath9k_hw_setslottime(ah
, (ackto
- 3) / 2);
344 ath9k_hw_set_ack_timeout(ah
, ackto
);
345 ath9k_hw_set_cts_timeout(ah
, ackto
);
347 EXPORT_SYMBOL(ath_dynack_reset
);
350 * ath_dynack_init - init dynack data structure
354 void ath_dynack_init(struct ath_hw
*ah
)
356 struct ath_dynack
*da
= &ah
->dynack
;
358 memset(da
, 0, sizeof(struct ath_dynack
));
360 spin_lock_init(&da
->qlock
);
361 INIT_LIST_HEAD(&da
->nodes
);
363 ah
->hw
->wiphy
->features
|= NL80211_FEATURE_ACKTO_ESTIMATION
;