Commit 1d60ab05 authored by Stefano Brivio's avatar Stefano Brivio Committed by John W. Linville

rc80211-pid: fix rate adjustment

Merge rate_control_pid_shift_adjust() to rate_control_pid_adjust_rate()
in order to make the learning algorithm aware of constraints on rates. Also
add some comments and rename variables.

This fixes a bug which prevented 802.11b/g non-AP STAs from working with
802.11b only AP STAs.

This patch was originally destined for 2.6.26, and is being backported
to fix a user reported problem in post-2.6.24 kernels.
Signed-off-by: default avatarStefano Brivio <stefano.brivio@polimi.it>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent ec9b6add
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Copyright 2002-2005, Instant802 Networks, Inc. * Copyright 2002-2005, Instant802 Networks, Inc.
* Copyright 2005, Devicescape Software, Inc. * Copyright 2005, Devicescape Software, Inc.
* Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de> * 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 * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -63,72 +63,66 @@ ...@@ -63,72 +63,66 @@
* RC_PID_ARITH_SHIFT. * RC_PID_ARITH_SHIFT.
*/ */
/* Adjust the rate while ensuring that we won't switch to a lower rate if it
/* Shift the adjustment so that we won't switch to a lower rate if it exhibited * exhibited a worse failed frames behaviour and we'll choose the highest rate
* a worse failed frames behaviour and we'll choose the highest rate whose * whose failed frames behaviour is not worse than the one of the original rate
* failed frames behaviour is not worse than the one of the original rate * target. While at it, check that the new rate is valid. */
* 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;
}
static void rate_control_pid_adjust_rate(struct ieee80211_local *local, static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
struct sta_info *sta, int adj, struct sta_info *sta, int adj,
struct rc_pid_rateinfo *rinfo) struct rc_pid_rateinfo *rinfo)
{ {
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
struct ieee80211_hw_mode *mode; struct ieee80211_hw_mode *mode;
int newidx; int cur_sorted, new_sorted, probe, tmp, n_bitrates;
int maxrate; int cur = sta->txrate;
int back = (adj > 0) ? 1 : -1;
sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
mode = local->oper_hw_mode; 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, /* Map passed arguments to sorted values. */
mode->num_rates); cur_sorted = rinfo[cur].rev_index;
new_sorted = cur_sorted + adj;
while (newidx != sta->txrate) { /* Check limits. */
if (rate_supported(sta, mode, newidx) && if (new_sorted < 0)
(maxrate < 0 || newidx <= maxrate)) { new_sorted = rinfo[0].rev_index;
sta->txrate = newidx; else if (new_sorted >= n_bitrates)
break; new_sorted = rinfo[n_bitrates - 1].rev_index;
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;
} }
newidx += back; /* 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 #ifdef CONFIG_MAC80211_DEBUGFS
rate_control_pid_event_rate_change( rate_control_pid_event_rate_change(
&((struct rc_pid_sta_info *)sta->rate_ctrl_priv)->events, &((struct rc_pid_sta_info *)sta->rate_ctrl_priv)->events,
newidx, mode->rates[newidx].rate); cur, mode->rates[cur].rate);
#endif #endif
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment