diff options
author | Mattias Nissler <mattias.nissler@gmx.de> | 2007-12-20 13:50:07 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 14:59:17 -0800 |
commit | 1abbe498e4b5e4f2000dfc30a0fa25be9553530e (patch) | |
tree | 8f899d2f623b2316f874fd8ae4b84838ad4e8b40 /net/mac80211/ieee80211_rate.c | |
parent | 98f0b0a3a412eade153c7cf00c6b863600980d89 (diff) |
mac80211: clean up rate selection
Move some code out of rc80211_simple since it's probably needed for all rate
selection algorithms, and fix iwlwifi accordingly. While at it, clean up the
rate_control_get_rate() interface.
Signed-off-by: Stefano Brivio <stefano.brivio@polimi.it>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mac80211/ieee80211_rate.c')
-rw-r--r-- | net/mac80211/ieee80211_rate.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/net/mac80211/ieee80211_rate.c b/net/mac80211/ieee80211_rate.c index c3f27839374..e495b0998b4 100644 --- a/net/mac80211/ieee80211_rate.c +++ b/net/mac80211/ieee80211_rate.c @@ -147,6 +147,53 @@ static void rate_control_release(struct kref *kref) kfree(ctrl_ref); } +void rate_control_get_rate(struct net_device *dev, + struct ieee80211_hw_mode *mode, struct sk_buff *skb, + struct rate_selection *sel) +{ + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct rate_control_ref *ref = local->rate_ctrl; + struct ieee80211_sub_if_data *sdata; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct sta_info *sta = sta_info_get(local, hdr->addr1); + int i; + u16 fc; + + memset(sel, 0, sizeof(struct rate_selection)); + + /* Send management frames and broadcast/multicast data using lowest + * rate. */ + fc = le16_to_cpu(hdr->frame_control); + if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || + is_multicast_ether_addr(hdr->addr1)) + sel->rate = rate_lowest(local, mode, sta); + + /* If a forced rate is in effect, select it. */ + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) + sel->rate = &mode->rates[sdata->bss->force_unicast_rateidx]; + + /* If we haven't found the rate yet, ask the rate control algo. */ + if (!sel->rate) + ref->ops->get_rate(ref->priv, dev, mode, skb, sel); + + /* Select a non-ERP backup rate. */ + if (!sel->nonerp) { + for (i = 0; i < mode->num_rates - 1; i++) { + struct ieee80211_rate *rate = &mode->rates[i]; + if (sel->rate->rate < rate->rate) + break; + + if (rate_supported(sta, mode, i) && + !(rate->flags & IEEE80211_RATE_ERP)) + sel->nonerp = rate; + } + } + + if (sta) + sta_info_put(sta); +} + struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) { kref_get(&ref->kref); |