| .. | .. |
|---|
| 20 | 20 | |
|---|
| 21 | 21 | #define COMPUTE_TO (5 * HZ) |
|---|
| 22 | 22 | #define LATEACK_DELAY (10 * HZ) |
|---|
| 23 | | -#define LATEACK_TO 256 |
|---|
| 24 | | -#define MAX_DELAY 300 |
|---|
| 25 | 23 | #define EWMA_LEVEL 96 |
|---|
| 26 | 24 | #define EWMA_DIV 128 |
|---|
| 25 | + |
|---|
| 26 | +/** |
|---|
| 27 | + * ath_dynack_get_max_to - set max timeout according to channel width |
|---|
| 28 | + * @ah: ath hw |
|---|
| 29 | + * |
|---|
| 30 | + */ |
|---|
| 31 | +static u32 ath_dynack_get_max_to(struct ath_hw *ah) |
|---|
| 32 | +{ |
|---|
| 33 | + const struct ath9k_channel *chan = ah->curchan; |
|---|
| 34 | + |
|---|
| 35 | + if (!chan) |
|---|
| 36 | + return 300; |
|---|
| 37 | + |
|---|
| 38 | + if (IS_CHAN_HT40(chan)) |
|---|
| 39 | + return 300; |
|---|
| 40 | + if (IS_CHAN_HALF_RATE(chan)) |
|---|
| 41 | + return 750; |
|---|
| 42 | + if (IS_CHAN_QUARTER_RATE(chan)) |
|---|
| 43 | + return 1500; |
|---|
| 44 | + return 600; |
|---|
| 45 | +} |
|---|
| 27 | 46 | |
|---|
| 28 | 47 | /** |
|---|
| 29 | 48 | * ath_dynack_ewma - EWMA (Exponentially Weighted Moving Average) calculation |
|---|
| .. | .. |
|---|
| 79 | 98 | } |
|---|
| 80 | 99 | |
|---|
| 81 | 100 | /** |
|---|
| 101 | + * ath_dynack_set_timeout - configure timeouts/slottime registers |
|---|
| 102 | + * @ah: ath hw |
|---|
| 103 | + * @to: timeout value |
|---|
| 104 | + * |
|---|
| 105 | + */ |
|---|
| 106 | +static void ath_dynack_set_timeout(struct ath_hw *ah, int to) |
|---|
| 107 | +{ |
|---|
| 108 | + struct ath_common *common = ath9k_hw_common(ah); |
|---|
| 109 | + int slottime = (to - 3) / 2; |
|---|
| 110 | + |
|---|
| 111 | + ath_dbg(common, DYNACK, "ACK timeout %u slottime %u\n", |
|---|
| 112 | + to, slottime); |
|---|
| 113 | + ath9k_hw_setslottime(ah, slottime); |
|---|
| 114 | + ath9k_hw_set_ack_timeout(ah, to); |
|---|
| 115 | + ath9k_hw_set_cts_timeout(ah, to); |
|---|
| 116 | +} |
|---|
| 117 | + |
|---|
| 118 | +/** |
|---|
| 82 | 119 | * ath_dynack_compute_ackto - compute ACK timeout as the maximum STA timeout |
|---|
| 83 | 120 | * @ah: ath hw |
|---|
| 84 | 121 | * |
|---|
| .. | .. |
|---|
| 86 | 123 | */ |
|---|
| 87 | 124 | static void ath_dynack_compute_ackto(struct ath_hw *ah) |
|---|
| 88 | 125 | { |
|---|
| 89 | | - struct ath_common *common = ath9k_hw_common(ah); |
|---|
| 90 | 126 | struct ath_dynack *da = &ah->dynack; |
|---|
| 91 | 127 | struct ath_node *an; |
|---|
| 92 | 128 | int to = 0; |
|---|
| .. | .. |
|---|
| 96 | 132 | to = an->ackto; |
|---|
| 97 | 133 | |
|---|
| 98 | 134 | if (to && da->ackto != to) { |
|---|
| 99 | | - u32 slottime; |
|---|
| 100 | | - |
|---|
| 101 | | - slottime = (to - 3) / 2; |
|---|
| 135 | + ath_dynack_set_timeout(ah, to); |
|---|
| 102 | 136 | da->ackto = to; |
|---|
| 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); |
|---|
| 108 | 137 | } |
|---|
| 109 | 138 | } |
|---|
| 110 | 139 | |
|---|
| .. | .. |
|---|
| 116 | 145 | */ |
|---|
| 117 | 146 | static void ath_dynack_compute_to(struct ath_hw *ah) |
|---|
| 118 | 147 | { |
|---|
| 119 | | - u32 ackto, ack_ts; |
|---|
| 120 | | - u8 *dst, *src; |
|---|
| 121 | | - struct ieee80211_sta *sta; |
|---|
| 122 | | - struct ath_node *an; |
|---|
| 123 | | - struct ts_info *st_ts; |
|---|
| 124 | 148 | struct ath_dynack *da = &ah->dynack; |
|---|
| 149 | + u32 ackto, ack_ts, max_to; |
|---|
| 150 | + struct ieee80211_sta *sta; |
|---|
| 151 | + struct ts_info *st_ts; |
|---|
| 152 | + struct ath_node *an; |
|---|
| 153 | + u8 *dst, *src; |
|---|
| 125 | 154 | |
|---|
| 126 | 155 | rcu_read_lock(); |
|---|
| 127 | 156 | |
|---|
| 157 | + max_to = ath_dynack_get_max_to(ah); |
|---|
| 128 | 158 | while (da->st_rbf.h_rb != da->st_rbf.t_rb && |
|---|
| 129 | 159 | da->ack_rbf.h_rb != da->ack_rbf.t_rb) { |
|---|
| 130 | 160 | ack_ts = da->ack_rbf.tstamp[da->ack_rbf.h_rb]; |
|---|
| .. | .. |
|---|
| 140 | 170 | if (ack_ts > st_ts->tstamp + st_ts->dur) { |
|---|
| 141 | 171 | ackto = ack_ts - st_ts->tstamp - st_ts->dur; |
|---|
| 142 | 172 | |
|---|
| 143 | | - if (ackto < MAX_DELAY) { |
|---|
| 173 | + if (ackto < max_to) { |
|---|
| 144 | 174 | sta = ieee80211_find_sta_by_ifaddr(ah->hw, dst, |
|---|
| 145 | 175 | src); |
|---|
| 146 | 176 | if (sta) { |
|---|
| .. | .. |
|---|
| 178 | 208 | struct ath_tx_status *ts, |
|---|
| 179 | 209 | struct ieee80211_sta *sta) |
|---|
| 180 | 210 | { |
|---|
| 181 | | - u8 ridx; |
|---|
| 182 | 211 | struct ieee80211_hdr *hdr; |
|---|
| 183 | 212 | struct ath_dynack *da = &ah->dynack; |
|---|
| 184 | 213 | struct ath_common *common = ath9k_hw_common(ah); |
|---|
| 185 | 214 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
|---|
| 215 | + u32 dur = ts->duration; |
|---|
| 216 | + u8 ridx; |
|---|
| 186 | 217 | |
|---|
| 187 | 218 | if (!da->enabled || (info->flags & IEEE80211_TX_CTL_NO_ACK)) |
|---|
| 188 | 219 | return; |
|---|
| .. | .. |
|---|
| 196 | 227 | if (ieee80211_is_assoc_req(hdr->frame_control) || |
|---|
| 197 | 228 | ieee80211_is_assoc_resp(hdr->frame_control) || |
|---|
| 198 | 229 | ieee80211_is_auth(hdr->frame_control)) { |
|---|
| 199 | | - ath_dbg(common, DYNACK, "late ack\n"); |
|---|
| 230 | + u32 max_to = ath_dynack_get_max_to(ah); |
|---|
| 200 | 231 | |
|---|
| 201 | | - ath9k_hw_setslottime(ah, (LATEACK_TO - 3) / 2); |
|---|
| 202 | | - ath9k_hw_set_ack_timeout(ah, LATEACK_TO); |
|---|
| 203 | | - ath9k_hw_set_cts_timeout(ah, LATEACK_TO); |
|---|
| 232 | + ath_dbg(common, DYNACK, "late ack\n"); |
|---|
| 233 | + ath_dynack_set_timeout(ah, max_to); |
|---|
| 204 | 234 | if (sta) { |
|---|
| 205 | 235 | struct ath_node *an; |
|---|
| 206 | 236 | |
|---|
| .. | .. |
|---|
| 217 | 247 | ridx = ts->ts_rateindex; |
|---|
| 218 | 248 | |
|---|
| 219 | 249 | da->st_rbf.ts[da->st_rbf.t_rb].tstamp = ts->ts_tstamp; |
|---|
| 220 | | - da->st_rbf.ts[da->st_rbf.t_rb].dur = ts->duration; |
|---|
| 221 | 250 | ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_dest, hdr->addr1); |
|---|
| 222 | 251 | ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_src, hdr->addr2); |
|---|
| 223 | 252 | |
|---|
| 224 | 253 | if (!(info->status.rates[ridx].flags & IEEE80211_TX_RC_MCS)) { |
|---|
| 225 | | - u32 phy, sifs; |
|---|
| 226 | 254 | const struct ieee80211_rate *rate; |
|---|
| 227 | 255 | struct ieee80211_tx_rate *rates = info->status.rates; |
|---|
| 256 | + u32 phy; |
|---|
| 228 | 257 | |
|---|
| 229 | 258 | rate = &common->sbands[info->band].bitrates[rates[ridx].idx]; |
|---|
| 230 | 259 | if (info->band == NL80211_BAND_2GHZ && |
|---|
| .. | .. |
|---|
| 233 | 262 | else |
|---|
| 234 | 263 | phy = WLAN_RC_PHY_OFDM; |
|---|
| 235 | 264 | |
|---|
| 236 | | - sifs = ath_dynack_get_sifs(ah, phy); |
|---|
| 237 | | - da->st_rbf.ts[da->st_rbf.t_rb].dur -= sifs; |
|---|
| 265 | + dur -= ath_dynack_get_sifs(ah, phy); |
|---|
| 238 | 266 | } |
|---|
| 239 | | - |
|---|
| 240 | | - ath_dbg(common, DYNACK, "{%pM} tx sample %u [dur %u][h %u-t %u]\n", |
|---|
| 241 | | - hdr->addr1, da->st_rbf.ts[da->st_rbf.t_rb].tstamp, |
|---|
| 242 | | - da->st_rbf.ts[da->st_rbf.t_rb].dur, da->st_rbf.h_rb, |
|---|
| 243 | | - (da->st_rbf.t_rb + 1) % ATH_DYN_BUF); |
|---|
| 267 | + da->st_rbf.ts[da->st_rbf.t_rb].dur = dur; |
|---|
| 244 | 268 | |
|---|
| 245 | 269 | INCR(da->st_rbf.t_rb, ATH_DYN_BUF); |
|---|
| 246 | 270 | if (da->st_rbf.t_rb == da->st_rbf.h_rb) |
|---|
| 247 | 271 | INCR(da->st_rbf.h_rb, ATH_DYN_BUF); |
|---|
| 272 | + |
|---|
| 273 | + ath_dbg(common, DYNACK, "{%pM} tx sample %u [dur %u][h %u-t %u]\n", |
|---|
| 274 | + hdr->addr1, ts->ts_tstamp, dur, da->st_rbf.h_rb, |
|---|
| 275 | + da->st_rbf.t_rb); |
|---|
| 248 | 276 | |
|---|
| 249 | 277 | ath_dynack_compute_to(ah); |
|---|
| 250 | 278 | |
|---|
| .. | .. |
|---|
| 272 | 300 | spin_lock_bh(&da->qlock); |
|---|
| 273 | 301 | da->ack_rbf.tstamp[da->ack_rbf.t_rb] = ts; |
|---|
| 274 | 302 | |
|---|
| 275 | | - ath_dbg(common, DYNACK, "rx sample %u [h %u-t %u]\n", |
|---|
| 276 | | - da->ack_rbf.tstamp[da->ack_rbf.t_rb], |
|---|
| 277 | | - da->ack_rbf.h_rb, (da->ack_rbf.t_rb + 1) % ATH_DYN_BUF); |
|---|
| 278 | | - |
|---|
| 279 | 303 | INCR(da->ack_rbf.t_rb, ATH_DYN_BUF); |
|---|
| 280 | 304 | if (da->ack_rbf.t_rb == da->ack_rbf.h_rb) |
|---|
| 281 | 305 | INCR(da->ack_rbf.h_rb, ATH_DYN_BUF); |
|---|
| 306 | + |
|---|
| 307 | + ath_dbg(common, DYNACK, "rx sample %u [h %u-t %u]\n", |
|---|
| 308 | + ts, da->ack_rbf.h_rb, da->ack_rbf.t_rb); |
|---|
| 282 | 309 | |
|---|
| 283 | 310 | ath_dynack_compute_to(ah); |
|---|
| 284 | 311 | |
|---|
| .. | .. |
|---|
| 294 | 321 | */ |
|---|
| 295 | 322 | void ath_dynack_node_init(struct ath_hw *ah, struct ath_node *an) |
|---|
| 296 | 323 | { |
|---|
| 297 | | - /* ackto = slottime + sifs + air delay */ |
|---|
| 298 | | - u32 ackto = 9 + 16 + 64; |
|---|
| 299 | 324 | struct ath_dynack *da = &ah->dynack; |
|---|
| 300 | 325 | |
|---|
| 301 | | - an->ackto = ackto; |
|---|
| 326 | + an->ackto = da->ackto; |
|---|
| 302 | 327 | |
|---|
| 303 | 328 | spin_lock_bh(&da->qlock); |
|---|
| 304 | 329 | list_add_tail(&an->list, &da->nodes); |
|---|
| .. | .. |
|---|
| 329 | 354 | */ |
|---|
| 330 | 355 | void ath_dynack_reset(struct ath_hw *ah) |
|---|
| 331 | 356 | { |
|---|
| 332 | | - /* ackto = slottime + sifs + air delay */ |
|---|
| 333 | | - u32 ackto = 9 + 16 + 64; |
|---|
| 334 | 357 | struct ath_dynack *da = &ah->dynack; |
|---|
| 358 | + struct ath_node *an; |
|---|
| 335 | 359 | |
|---|
| 336 | | - da->lto = jiffies; |
|---|
| 337 | | - da->ackto = ackto; |
|---|
| 360 | + spin_lock_bh(&da->qlock); |
|---|
| 361 | + |
|---|
| 362 | + da->lto = jiffies + COMPUTE_TO; |
|---|
| 338 | 363 | |
|---|
| 339 | 364 | da->st_rbf.t_rb = 0; |
|---|
| 340 | 365 | da->st_rbf.h_rb = 0; |
|---|
| 341 | 366 | da->ack_rbf.t_rb = 0; |
|---|
| 342 | 367 | da->ack_rbf.h_rb = 0; |
|---|
| 343 | 368 | |
|---|
| 369 | + da->ackto = ath_dynack_get_max_to(ah); |
|---|
| 370 | + list_for_each_entry(an, &da->nodes, list) |
|---|
| 371 | + an->ackto = da->ackto; |
|---|
| 372 | + |
|---|
| 344 | 373 | /* init acktimeout */ |
|---|
| 345 | | - ath9k_hw_setslottime(ah, (ackto - 3) / 2); |
|---|
| 346 | | - ath9k_hw_set_ack_timeout(ah, ackto); |
|---|
| 347 | | - ath9k_hw_set_cts_timeout(ah, ackto); |
|---|
| 374 | + ath_dynack_set_timeout(ah, da->ackto); |
|---|
| 375 | + |
|---|
| 376 | + spin_unlock_bh(&da->qlock); |
|---|
| 348 | 377 | } |
|---|
| 349 | 378 | EXPORT_SYMBOL(ath_dynack_reset); |
|---|
| 350 | 379 | |
|---|
| .. | .. |
|---|
| 361 | 390 | |
|---|
| 362 | 391 | spin_lock_init(&da->qlock); |
|---|
| 363 | 392 | INIT_LIST_HEAD(&da->nodes); |
|---|
| 393 | + /* ackto = slottime + sifs + air delay */ |
|---|
| 394 | + da->ackto = 9 + 16 + 64; |
|---|
| 364 | 395 | |
|---|
| 365 | 396 | ah->hw->wiphy->features |= NL80211_FEATURE_ACKTO_ESTIMATION; |
|---|
| 366 | 397 | } |
|---|