X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fmac80211%2Frc80211_pid_algo.c;h=a849b745bdb56b6f83b19a98e73f069f42341621;hb=f974a8ec96571535ee07880a023bcce0e3f2c76b;hp=c5a607ca84401421a631f450518934dbb6baf872;hpb=8318d78a44d49ac1edf2bdec7299de3617c4232e;p=linux-2.6 diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index c5a607ca84..a849b745bd 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -2,7 +2,7 @@ * Copyright 2002-2005, Instant802 Networks, Inc. * Copyright 2005, Devicescape Software, Inc. * Copyright 2007, Mattias Nissler - * Copyright 2007, Stefano Brivio + * Copyright 2007-2008, Stefano Brivio * * 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 @@ -14,8 +14,8 @@ #include #include #include -#include "ieee80211_rate.h" - +#include "rate.h" +#include "mesh.h" #include "rc80211_pid.h" @@ -64,71 +64,66 @@ */ -/* 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_supported_band *sband; - int newidx; - int maxrate; - int back = (adj > 0) ? 1 : -1; - - sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); + int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; + int cur = sta->txrate_idx; + sdata = sta->sdata; 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, - sband->n_bitrates); + /* Map passed arguments to sorted values. */ + cur_sorted = rinfo[cur].rev_index; + new_sorted = cur_sorted + adj; - while (newidx != sta->txrate_idx) { - if (rate_supported(sta, sband->band, newidx) && - (maxrate < 0 || newidx <= maxrate)) { - sta->txrate_idx = 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; + + tmp = new_sorted; - newidx += back; + 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; } + /* 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 rate_control_pid_event_rate_change( &((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 } @@ -153,6 +148,9 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, struct ieee80211_local *local, struct sta_info *sta) { +#ifdef CONFIG_MAC80211_MESH + struct ieee80211_sub_if_data *sdata = sta->sdata; +#endif struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; struct rc_pid_rateinfo *rinfo = pinfo->rinfo; struct ieee80211_supported_band *sband; @@ -183,7 +181,14 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, pf = spinfo->last_pf; else { pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; +#ifdef CONFIG_MAC80211_MESH + if (pf == 100 && + sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) + mesh_plink_broken(sta); +#endif pf <<= RC_PID_ARITH_SHIFT; + sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) + >> RC_PID_ARITH_SHIFT; } spinfo->tx_num_xmit = 0; @@ -244,23 +249,25 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, unsigned long period; struct ieee80211_supported_band *sband; + rcu_read_lock(); + sta = sta_info_get(local, hdr->addr1); sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; if (!sta) - return; + goto unlock; /* Don't update the state if we're not controlling the rate. */ - sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); + sdata = sta->sdata; if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) { sta->txrate_idx = sdata->bss->max_ratectrl_rateidx; - return; + goto unlock; } /* Ignore all frames that were sent with a different rate than the rate * we currently advise mac80211 to use. */ if (status->control.tx_rate != &sband->bitrates[sta->txrate_idx]) - goto ignore; + goto unlock; spinfo = sta->rate_ctrl_priv; spinfo->tx_num_xmit++; @@ -285,9 +292,6 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, sta->tx_num_consecutive_failures++; sta->tx_num_mpdu_fail++; } else { - sta->last_ack_rssi[0] = sta->last_ack_rssi[1]; - sta->last_ack_rssi[1] = sta->last_ack_rssi[2]; - sta->last_ack_rssi[2] = status->ack_signal; sta->tx_num_consecutive_failures = 0; sta->tx_num_mpdu_ok++; } @@ -301,8 +305,8 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, if (time_after(jiffies, spinfo->last_sample + period)) rate_control_pid_sample(pinfo, local, sta); -ignore: - sta_info_put(sta); + unlock: + rcu_read_unlock(); } static void rate_control_pid_get_rate(void *priv, struct net_device *dev, @@ -317,6 +321,8 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev, int rateidx; u16 fc; + rcu_read_lock(); + sta = sta_info_get(local, hdr->addr1); /* Send management frames and broadcast/multicast data using lowest @@ -325,8 +331,7 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev, if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || is_multicast_ether_addr(hdr->addr1) || !sta) { sel->rate = rate_lowest(local, sband, sta); - if (sta) - sta_info_put(sta); + rcu_read_unlock(); return; } @@ -342,7 +347,7 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev, sta->last_txrate_idx = rateidx; - sta_info_put(sta); + rcu_read_unlock(); sel->rate = &sband->bitrates[rateidx]; @@ -365,6 +370,7 @@ static void rate_control_pid_rate_init(void *priv, void *priv_sta, sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; sta->txrate_idx = rate_lowest_index(local, sband, sta); + sta->fail_avg = 0; } static void *rate_control_pid_alloc(struct ieee80211_local *local)