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 u32
ath_dynack_ewma(u32 old
, u32
new)
34 return (new * (EWMA_DIV
- EWMA_LEVEL
) + old
* EWMA_LEVEL
) / EWMA_DIV
;
38 * ath_dynack_get_sifs - get sifs time based on phy used
43 static inline u32
ath_dynack_get_sifs(struct ath_hw
*ah
, int phy
)
45 u32 sifs
= CCK_SIFS_TIME
;
47 if (phy
== WLAN_RC_PHY_OFDM
) {
48 if (IS_CHAN_QUARTER_RATE(ah
->curchan
))
49 sifs
= OFDM_SIFS_TIME_QUARTER
;
50 else if (IS_CHAN_HALF_RATE(ah
->curchan
))
51 sifs
= OFDM_SIFS_TIME_HALF
;
53 sifs
= OFDM_SIFS_TIME
;
59 * ath_dynack_bssidmask - filter out ACK frames based on BSSID mask
61 * @mac: receiver address
63 static inline bool ath_dynack_bssidmask(struct ath_hw
*ah
, const u8
*mac
)
66 struct ath_common
*common
= ath9k_hw_common(ah
);
68 for (i
= 0; i
< ETH_ALEN
; i
++) {
69 if ((common
->macaddr
[i
] & common
->bssidmask
[i
]) !=
70 (mac
[i
] & common
->bssidmask
[i
]))
78 * ath_dynack_compute_ackto - compute ACK timeout as the maximum STA timeout
81 * should be called while holding qlock
83 static void ath_dynack_compute_ackto(struct ath_hw
*ah
)
87 struct ath_dynack
*da
= &ah
->dynack
;
88 struct ath_common
*common
= ath9k_hw_common(ah
);
90 list_for_each_entry(an
, &da
->nodes
, list
)
94 if (to
&& da
->ackto
!= to
) {
97 slottime
= (to
- 3) / 2;
99 ath_dbg(common
, DYNACK
, "ACK timeout %u slottime %u\n",
100 da
->ackto
, slottime
);
101 ath9k_hw_setslottime(ah
, slottime
);
102 ath9k_hw_set_ack_timeout(ah
, da
->ackto
);
103 ath9k_hw_set_cts_timeout(ah
, da
->ackto
);
108 * ath_dynack_compute_to - compute STA ACK timeout
111 * should be called while holding qlock
113 static void ath_dynack_compute_to(struct ath_hw
*ah
)
117 struct ieee80211_sta
*sta
;
119 struct ts_info
*st_ts
;
120 struct ath_dynack
*da
= &ah
->dynack
;
124 while (da
->st_rbf
.h_rb
!= da
->st_rbf
.t_rb
&&
125 da
->ack_rbf
.h_rb
!= da
->ack_rbf
.t_rb
) {
126 ack_ts
= da
->ack_rbf
.tstamp
[da
->ack_rbf
.h_rb
];
127 st_ts
= &da
->st_rbf
.ts
[da
->st_rbf
.h_rb
];
128 dst
= da
->st_rbf
.addr
[da
->st_rbf
.h_rb
].h_dest
;
129 src
= da
->st_rbf
.addr
[da
->st_rbf
.h_rb
].h_src
;
131 ath_dbg(ath9k_hw_common(ah
), DYNACK
,
132 "ack_ts %u st_ts %u st_dur %u [%u-%u]\n",
133 ack_ts
, st_ts
->tstamp
, st_ts
->dur
,
134 da
->ack_rbf
.h_rb
, da
->st_rbf
.h_rb
);
136 if (ack_ts
> st_ts
->tstamp
+ st_ts
->dur
) {
137 ackto
= ack_ts
- st_ts
->tstamp
- st_ts
->dur
;
139 if (ackto
< MAX_DELAY
) {
140 sta
= ieee80211_find_sta_by_ifaddr(ah
->hw
, dst
,
143 an
= (struct ath_node
*)sta
->drv_priv
;
144 an
->ackto
= ath_dynack_ewma(an
->ackto
,
146 ath_dbg(ath9k_hw_common(ah
), DYNACK
,
147 "%pM to %u\n", dst
, an
->ackto
);
148 if (time_is_before_jiffies(da
->lto
)) {
149 ath_dynack_compute_ackto(ah
);
150 da
->lto
= jiffies
+ COMPUTE_TO
;
153 INCR(da
->ack_rbf
.h_rb
, ATH_DYN_BUF
);
155 INCR(da
->st_rbf
.h_rb
, ATH_DYN_BUF
);
157 INCR(da
->ack_rbf
.h_rb
, ATH_DYN_BUF
);
165 * ath_dynack_sample_tx_ts - status timestamp sampling method
167 * @skb: socket buffer
168 * @ts: tx status info
171 void ath_dynack_sample_tx_ts(struct ath_hw
*ah
, struct sk_buff
*skb
,
172 struct ath_tx_status
*ts
)
175 struct ieee80211_hdr
*hdr
;
176 struct ath_dynack
*da
= &ah
->dynack
;
177 struct ath_common
*common
= ath9k_hw_common(ah
);
178 struct ieee80211_tx_info
*info
= IEEE80211_SKB_CB(skb
);
180 if ((info
->flags
& IEEE80211_TX_CTL_NO_ACK
) || !da
->enabled
)
183 spin_lock_bh(&da
->qlock
);
185 hdr
= (struct ieee80211_hdr
*)skb
->data
;
188 if (ts
->ts_status
& ATH9K_TXERR_XRETRY
) {
189 if (ieee80211_is_assoc_req(hdr
->frame_control
) ||
190 ieee80211_is_assoc_resp(hdr
->frame_control
)) {
191 ath_dbg(common
, DYNACK
, "late ack\n");
192 ath9k_hw_setslottime(ah
, (LATEACK_TO
- 3) / 2);
193 ath9k_hw_set_ack_timeout(ah
, LATEACK_TO
);
194 ath9k_hw_set_cts_timeout(ah
, LATEACK_TO
);
195 da
->lto
= jiffies
+ LATEACK_DELAY
;
198 spin_unlock_bh(&da
->qlock
);
202 ridx
= ts
->ts_rateindex
;
204 da
->st_rbf
.ts
[da
->st_rbf
.t_rb
].tstamp
= ts
->ts_tstamp
;
205 da
->st_rbf
.ts
[da
->st_rbf
.t_rb
].dur
= ts
->duration
;
206 ether_addr_copy(da
->st_rbf
.addr
[da
->st_rbf
.t_rb
].h_dest
, hdr
->addr1
);
207 ether_addr_copy(da
->st_rbf
.addr
[da
->st_rbf
.t_rb
].h_src
, hdr
->addr2
);
209 if (!(info
->status
.rates
[ridx
].flags
& IEEE80211_TX_RC_MCS
)) {
211 const struct ieee80211_rate
*rate
;
212 struct ieee80211_tx_rate
*rates
= info
->status
.rates
;
214 rate
= &common
->sbands
[info
->band
].bitrates
[rates
[ridx
].idx
];
215 if (info
->band
== IEEE80211_BAND_2GHZ
&&
216 !(rate
->flags
& IEEE80211_RATE_ERP_G
))
217 phy
= WLAN_RC_PHY_CCK
;
219 phy
= WLAN_RC_PHY_OFDM
;
221 sifs
= ath_dynack_get_sifs(ah
, phy
);
222 da
->st_rbf
.ts
[da
->st_rbf
.t_rb
].dur
-= sifs
;
225 ath_dbg(common
, DYNACK
, "{%pM} tx sample %u [dur %u][h %u-t %u]\n",
226 hdr
->addr1
, da
->st_rbf
.ts
[da
->st_rbf
.t_rb
].tstamp
,
227 da
->st_rbf
.ts
[da
->st_rbf
.t_rb
].dur
, da
->st_rbf
.h_rb
,
228 (da
->st_rbf
.t_rb
+ 1) % ATH_DYN_BUF
);
230 INCR(da
->st_rbf
.t_rb
, ATH_DYN_BUF
);
231 if (da
->st_rbf
.t_rb
== da
->st_rbf
.h_rb
)
232 INCR(da
->st_rbf
.h_rb
, ATH_DYN_BUF
);
234 ath_dynack_compute_to(ah
);
236 spin_unlock_bh(&da
->qlock
);
238 EXPORT_SYMBOL(ath_dynack_sample_tx_ts
);
241 * ath_dynack_sample_ack_ts - ACK timestamp sampling method
243 * @skb: socket buffer
247 void ath_dynack_sample_ack_ts(struct ath_hw
*ah
, struct sk_buff
*skb
,
250 struct ath_dynack
*da
= &ah
->dynack
;
251 struct ath_common
*common
= ath9k_hw_common(ah
);
252 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*)skb
->data
;
254 if (!ath_dynack_bssidmask(ah
, hdr
->addr1
) || !da
->enabled
)
257 spin_lock_bh(&da
->qlock
);
258 da
->ack_rbf
.tstamp
[da
->ack_rbf
.t_rb
] = ts
;
260 ath_dbg(common
, DYNACK
, "rx sample %u [h %u-t %u]\n",
261 da
->ack_rbf
.tstamp
[da
->ack_rbf
.t_rb
],
262 da
->ack_rbf
.h_rb
, (da
->ack_rbf
.t_rb
+ 1) % ATH_DYN_BUF
);
264 INCR(da
->ack_rbf
.t_rb
, ATH_DYN_BUF
);
265 if (da
->ack_rbf
.t_rb
== da
->ack_rbf
.h_rb
)
266 INCR(da
->ack_rbf
.h_rb
, ATH_DYN_BUF
);
268 ath_dynack_compute_to(ah
);
270 spin_unlock_bh(&da
->qlock
);
272 EXPORT_SYMBOL(ath_dynack_sample_ack_ts
);
275 * ath_dynack_node_init - init ath_node related info
280 void ath_dynack_node_init(struct ath_hw
*ah
, struct ath_node
*an
)
282 /* ackto = slottime + sifs + air delay */
283 u32 ackto
= ATH9K_SLOT_TIME_9
+ 16 + 64;
284 struct ath_dynack
*da
= &ah
->dynack
;
288 spin_lock(&da
->qlock
);
289 list_add_tail(&an
->list
, &da
->nodes
);
290 spin_unlock(&da
->qlock
);
292 EXPORT_SYMBOL(ath_dynack_node_init
);
295 * ath_dynack_node_deinit - deinit ath_node related info
300 void ath_dynack_node_deinit(struct ath_hw
*ah
, struct ath_node
*an
)
302 struct ath_dynack
*da
= &ah
->dynack
;
304 spin_lock(&da
->qlock
);
306 spin_unlock(&da
->qlock
);
308 EXPORT_SYMBOL(ath_dynack_node_deinit
);
311 * ath_dynack_reset - reset dynack processing
315 void ath_dynack_reset(struct ath_hw
*ah
)
317 /* ackto = slottime + sifs + air delay */
318 u32 ackto
= ATH9K_SLOT_TIME_9
+ 16 + 64;
319 struct ath_dynack
*da
= &ah
->dynack
;
326 da
->ack_rbf
.t_rb
= 0;
327 da
->ack_rbf
.h_rb
= 0;
329 /* init acktimeout */
330 ath9k_hw_setslottime(ah
, (ackto
- 3) / 2);
331 ath9k_hw_set_ack_timeout(ah
, ackto
);
332 ath9k_hw_set_cts_timeout(ah
, ackto
);
334 EXPORT_SYMBOL(ath_dynack_reset
);
337 * ath_dynack_init - init dynack data structure
341 void ath_dynack_init(struct ath_hw
*ah
)
343 struct ath_dynack
*da
= &ah
->dynack
;
345 memset(da
, 0, sizeof(struct ath_dynack
));
347 spin_lock_init(&da
->qlock
);
348 INIT_LIST_HEAD(&da
->nodes
);
350 ah
->hw
->wiphy
->features
|= NL80211_FEATURE_ACKTO_ESTIMATION
;