|
|
|
@ -2,7 +2,7 @@ |
|
|
|
|
* Copyright 2002-2005, Instant802 Networks, Inc. |
|
|
|
|
* Copyright 2005, Devicescape Software, Inc. |
|
|
|
|
* Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de> |
|
|
|
|
* Copyright 2007, Stefano Brivio <stefano.brivio@polimi.it> |
|
|
|
|
* Copyright 2007-2008, Stefano Brivio <stefano.brivio@polimi.it> |
|
|
|
|
* |
|
|
|
|
* This program is free software; you can redistribute it and/or modify |
|
|
|
|
* it under the terms of the GNU General Public License version 2 as |
|
|
|
@ -63,72 +63,66 @@ |
|
|
|
|
* RC_PID_ARITH_SHIFT. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Shift the adjustment so that we won't switch to a lower rate if it exhibited
|
|
|
|
|
* a worse failed frames behaviour and we'll choose the highest rate whose |
|
|
|
|
* failed frames behaviour is not worse than the one of the original rate |
|
|
|
|
* target. While at it, check that the adjustment is within the ranges. Then, |
|
|
|
|
* provide the new rate index. */ |
|
|
|
|
static int rate_control_pid_shift_adjust(struct rc_pid_rateinfo *r, |
|
|
|
|
int adj, int cur, int l) |
|
|
|
|
{ |
|
|
|
|
int i, j, k, tmp; |
|
|
|
|
|
|
|
|
|
j = r[cur].rev_index; |
|
|
|
|
i = j + adj; |
|
|
|
|
|
|
|
|
|
if (i < 0) |
|
|
|
|
return r[0].index; |
|
|
|
|
if (i >= l - 1) |
|
|
|
|
return r[l - 1].index; |
|
|
|
|
|
|
|
|
|
tmp = i; |
|
|
|
|
|
|
|
|
|
if (adj < 0) { |
|
|
|
|
for (k = j; k >= i; k--) |
|
|
|
|
if (r[k].diff <= r[j].diff) |
|
|
|
|
tmp = k; |
|
|
|
|
} else { |
|
|
|
|
for (k = i + 1; k + i < l; k++) |
|
|
|
|
if (r[k].diff <= r[i].diff) |
|
|
|
|
tmp = k; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return r[tmp].index; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Adjust the rate while ensuring that we won't switch to a lower rate if it
|
|
|
|
|
* exhibited a worse failed frames behaviour and we'll choose the highest rate |
|
|
|
|
* whose failed frames behaviour is not worse than the one of the original rate |
|
|
|
|
* target. While at it, check that the new rate is valid. */ |
|
|
|
|
static void rate_control_pid_adjust_rate(struct ieee80211_local *local, |
|
|
|
|
struct sta_info *sta, int adj, |
|
|
|
|
struct rc_pid_rateinfo *rinfo) |
|
|
|
|
{ |
|
|
|
|
struct ieee80211_sub_if_data *sdata; |
|
|
|
|
struct ieee80211_hw_mode *mode; |
|
|
|
|
int newidx; |
|
|
|
|
int maxrate; |
|
|
|
|
int back = (adj > 0) ? 1 : -1; |
|
|
|
|
int cur_sorted, new_sorted, probe, tmp, n_bitrates; |
|
|
|
|
int cur = sta->txrate; |
|
|
|
|
|
|
|
|
|
sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); |
|
|
|
|
|
|
|
|
|
mode = local->oper_hw_mode; |
|
|
|
|
maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1; |
|
|
|
|
n_bitrates = mode->num_rates; |
|
|
|
|
|
|
|
|
|
newidx = rate_control_pid_shift_adjust(rinfo, adj, sta->txrate, |
|
|
|
|
mode->num_rates); |
|
|
|
|
/* Map passed arguments to sorted values. */ |
|
|
|
|
cur_sorted = rinfo[cur].rev_index; |
|
|
|
|
new_sorted = cur_sorted + adj; |
|
|
|
|
|
|
|
|
|
while (newidx != sta->txrate) { |
|
|
|
|
if (rate_supported(sta, mode, newidx) && |
|
|
|
|
(maxrate < 0 || newidx <= maxrate)) { |
|
|
|
|
sta->txrate = newidx; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
/* Check limits. */ |
|
|
|
|
if (new_sorted < 0) |
|
|
|
|
new_sorted = rinfo[0].rev_index; |
|
|
|
|
else if (new_sorted >= n_bitrates) |
|
|
|
|
new_sorted = rinfo[n_bitrates - 1].rev_index; |
|
|
|
|
|
|
|
|
|
newidx += back; |
|
|
|
|
tmp = new_sorted; |
|
|
|
|
|
|
|
|
|
if (adj < 0) { |
|
|
|
|
/* Ensure that the rate decrease isn't disadvantageous. */ |
|
|
|
|
for (probe = cur_sorted; probe >= new_sorted; probe--) |
|
|
|
|
if (rinfo[probe].diff <= rinfo[cur_sorted].diff && |
|
|
|
|
rate_supported(sta, mode, rinfo[probe].index)) |
|
|
|
|
tmp = probe; |
|
|
|
|
} else { |
|
|
|
|
/* Look for rate increase with zero (or below) cost. */ |
|
|
|
|
for (probe = new_sorted + 1; probe < n_bitrates; probe++) |
|
|
|
|
if (rinfo[probe].diff <= rinfo[new_sorted].diff && |
|
|
|
|
rate_supported(sta, mode, rinfo[probe].index)) |
|
|
|
|
tmp = probe; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Fit the rate found to the nearest supported rate. */ |
|
|
|
|
do { |
|
|
|
|
if (rate_supported(sta, mode, rinfo[tmp].index)) { |
|
|
|
|
sta->txrate = rinfo[tmp].index; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if (adj < 0) |
|
|
|
|
tmp--; |
|
|
|
|
else |
|
|
|
|
tmp++; |
|
|
|
|
} while (tmp < n_bitrates && tmp >= 0); |
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_MAC80211_DEBUGFS |
|
|
|
|
rate_control_pid_event_rate_change( |
|
|
|
|
&((struct rc_pid_sta_info *)sta->rate_ctrl_priv)->events, |
|
|
|
|
newidx, mode->rates[newidx].rate); |
|
|
|
|
cur, mode->rates[cur].rate); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|