Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b7c50de9 authored by Stefano Brivio's avatar Stefano Brivio Committed by John W. Linville
Browse files

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.

Signed-off-by: default avatarStefano Brivio <stefano.brivio@polimi.it>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 238814fd
Loading
Loading
Loading
Loading
+44 −49
Original line number Original line Diff line number Diff line
@@ -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
@@ -64,71 +64,66 @@
 */
 */




/* Shift the adjustment so that we won't switch to a lower rate if it exhibited
/* Adjust the rate while ensuring that we won't switch to a lower rate if it
 * a worse failed frames behaviour and we'll choose the highest rate whose
 * exhibited a worse failed frames behaviour and we'll choose the highest rate
 * failed frames behaviour is not worse than the one of the original 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,
 * target. While at it, check that the new rate is valid. */
 * 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_supported_band *sband;
	struct ieee80211_supported_band *sband;
	int newidx;
	int cur_sorted, new_sorted, probe, tmp, n_bitrates, band;
	int maxrate;
	int cur = sta->txrate_idx;
	int back = (adj > 0) ? 1 : -1;


	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);

	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
	maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1;
	band = sband->band;
	n_bitrates = sband->n_bitrates;


	newidx = rate_control_pid_shift_adjust(rinfo, adj, sta->txrate_idx,
	/* Map passed arguments to sorted values. */
					       sband->n_bitrates);
	cur_sorted = rinfo[cur].rev_index;
	new_sorted = cur_sorted + adj;


	while (newidx != sta->txrate_idx) {
	/* Check limits. */
		if (rate_supported(sta, sband->band, newidx) &&
	if (new_sorted < 0)
		    (maxrate < 0 || newidx <= maxrate)) {
		new_sorted = rinfo[0].rev_index;
			sta->txrate_idx = 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, band, 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, band, rinfo[probe].index))
				tmp = probe;
	}
	}


		newidx += back;
	/* Fit the rate found to the nearest supported rate. */
	do {
		if (rate_supported(sta, band, rinfo[tmp].index)) {
			sta->txrate_idx = 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, sband->bitrates[newidx].bitrate);
		sta->txrate_idx, sband->bitrates[sta->txrate_idx].bitrate);
#endif
#endif
}
}