summaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211_rate.c
diff options
context:
space:
mode:
authorMattias Nissler <mattias.nissler@gmx.de>2007-12-20 13:50:07 +0100
committerDavid S. Miller <davem@davemloft.net>2008-01-28 14:59:17 -0800
commit1abbe498e4b5e4f2000dfc30a0fa25be9553530e (patch)
tree8f899d2f623b2316f874fd8ae4b84838ad4e8b40 /net/mac80211/ieee80211_rate.c
parent98f0b0a3a412eade153c7cf00c6b863600980d89 (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.c47
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);