Introduce path_put()
[pandora-kernel.git] / net / mac80211 / rc80211_pid_algo.c
index b84e514..c339571 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/skbuff.h>
-
+#include <linux/debugfs.h>
 #include <net/mac80211.h>
 #include "ieee80211_rate.h"
 
@@ -74,29 +74,27 @@ static int rate_control_pid_shift_adjust(struct rc_pid_rateinfo *r,
 {
        int i, j, k, tmp;
 
-       if (cur + adj < 0)
-               return 0;
-       if (cur + adj >= l)
-               return l - 1;
+       j = r[cur].rev_index;
+       i = j + adj;
 
-       i = r[cur + adj].rev_index;
+       if (i < 0)
+               return r[0].index;
+       if (i >= l - 1)
+               return r[l - 1].index;
 
-       j = r[cur].rev_index;
+       tmp = i;
 
        if (adj < 0) {
-                       tmp = i;
-                       for (k = j; k >= i; k--)
-                               if (r[k].diff <= r[j].diff)
-                                       tmp = k;
-                       return r[tmp].index;
-       } else if (adj > 0) {
-                       tmp = i;
-                       for (k = i + 1; k + i < l; k++)
-                               if (r[k].diff <= r[i].diff)
-                                       tmp = k;
-                       return r[tmp].index;
+               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 cur + adj;
+
+       return r[tmp].index;
 }
 
 static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
@@ -110,10 +108,6 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
        int back = (adj > 0) ? 1 : -1;
 
        sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
-       if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
-               /* forced unicast rate - do not change STA rate */
-               return;
-       }
 
        mode = local->oper_hw_mode;
        maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1;
@@ -243,6 +237,7 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
 {
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_sub_if_data *sdata;
        struct rc_pid_info *pinfo = priv;
        struct sta_info *sta;
        struct rc_pid_sta_info *spinfo;
@@ -253,10 +248,17 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
        if (!sta)
                return;
 
+       /* Don't update the state if we're not controlling the rate. */
+       sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+       if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
+               sta->txrate = sdata->bss->max_ratectrl_rateidx;
+               return;
+       }
+
        /* Ignore all frames that were sent with a different rate than the rate
         * we currently advise mac80211 to use. */
        if (status->control.rate != &local->oper_hw_mode->rates[sta->txrate])
-               return;
+               goto ignore;
 
        spinfo = sta->rate_ctrl_priv;
        spinfo->tx_num_xmit++;
@@ -297,6 +299,7 @@ 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);
 }
 
@@ -307,22 +310,36 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
 {
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_sub_if_data *sdata;
        struct sta_info *sta;
        int rateidx;
+       u16 fc;
 
        sta = sta_info_get(local, hdr->addr1);
 
-       if (!sta) {
-               sel->rate = rate_lowest(local, mode, NULL);
-               sta_info_put(sta);
+       /* 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) || !sta) {
+               sel->rate = rate_lowest(local, mode, sta);
+               if (sta)
+                       sta_info_put(sta);
                return;
        }
 
+       /* 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)
+               sta->txrate = sdata->bss->force_unicast_rateidx;
+
        rateidx = sta->txrate;
 
        if (rateidx >= mode->num_rates)
                rateidx = mode->num_rates - 1;
 
+       sta->last_txrate = rateidx;
+
        sta_info_put(sta);
 
        sel->rate = &mode->rates[rateidx];
@@ -479,6 +496,8 @@ static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp)
        if (spinfo == NULL)
                return NULL;
 
+       spinfo->last_sample = jiffies;
+
 #ifdef CONFIG_MAC80211_DEBUGFS
        spin_lock_init(&spinfo->events.lock);
        init_waitqueue_head(&spinfo->events.waitqueue);
@@ -493,7 +512,7 @@ static void rate_control_pid_free_sta(void *priv, void *priv_sta)
        kfree(spinfo);
 }
 
-struct rate_control_ops mac80211_rcpid = {
+static struct rate_control_ops mac80211_rcpid = {
        .name = "pid",
        .tx_status = rate_control_pid_tx_status,
        .get_rate = rate_control_pid_get_rate,
@@ -508,3 +527,23 @@ struct rate_control_ops mac80211_rcpid = {
        .remove_sta_debugfs = rate_control_pid_remove_sta_debugfs,
 #endif
 };
+
+MODULE_DESCRIPTION("PID controller based rate control algorithm");
+MODULE_AUTHOR("Stefano Brivio");
+MODULE_AUTHOR("Mattias Nissler");
+MODULE_LICENSE("GPL");
+
+int __init rc80211_pid_init(void)
+{
+       return ieee80211_rate_control_register(&mac80211_rcpid);
+}
+
+void rc80211_pid_exit(void)
+{
+       ieee80211_rate_control_unregister(&mac80211_rcpid);
+}
+
+#ifdef CONFIG_MAC80211_RC_PID_MODULE
+module_init(rc80211_pid_init);
+module_exit(rc80211_pid_exit);
+#endif