rc80211-pid: export tuning parameters through debugfs
authorMattias Nissler <mattias.nissler@gmx.de>
Thu, 20 Dec 2007 12:27:26 +0000 (13:27 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Jan 2008 22:59:44 +0000 (14:59 -0800)
This adds all the tunable parameters used by rc80211_pid to debugfs for easy
testing and tuning.

Signed-off-by: Mattias Nissler <mattias.nissler@gmx.de>
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>
net/mac80211/rc80211_pid.h
net/mac80211/rc80211_pid_algo.c

index 5d0056c..425eb70 100644 (file)
@@ -119,6 +119,20 @@ struct rc_pid_events_file_info {
        unsigned int next_entry;
 };
 
+struct rc_pid_debugfs_entries {
+       struct dentry *dir;
+       struct dentry *target;
+       struct dentry *sampling_period;
+       struct dentry *coeff_p;
+       struct dentry *coeff_i;
+       struct dentry *coeff_d;
+       struct dentry *smoothing_shift;
+       struct dentry *sharpen_factor;
+       struct dentry *sharpen_duration;
+       struct dentry *norm_offset;
+       struct dentry *fast_start;
+};
+
 void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf,
                                             struct ieee80211_tx_status *stat);
 
@@ -222,8 +236,8 @@ struct rc_pid_info {
        /* Exponential averaging shift. */
        unsigned int smoothing_shift;
 
-       /* Sharpening shift and duration. */
-       unsigned int sharpen_shift;
+       /* Sharpening factor and duration. */
+       unsigned int sharpen_factor;
        unsigned int sharpen_duration;
 
        /* Normalization offset. */
@@ -237,6 +251,11 @@ struct rc_pid_info {
 
        /* Index of the last used rate. */
        int oldrate;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+       /* Debugfs entries created for the parameters above. */
+       struct rc_pid_debugfs_entries dentries;
+#endif
 };
 
 #endif /* RC80211_PID_H */
index 3fac3a5..631e468 100644 (file)
@@ -139,19 +139,20 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
 }
 
 /* Normalize the failed frames per-rate differences. */
-static void rate_control_pid_normalize(struct rc_pid_rateinfo *r, int l)
+static void rate_control_pid_normalize(struct rc_pid_info *pinfo, int l)
 {
-       int i;
+       int i, norm_offset = pinfo->norm_offset;
+       struct rc_pid_rateinfo *r = pinfo->rinfo;
 
-       if (r[0].diff > RC_PID_NORM_OFFSET)
-               r[0].diff -= RC_PID_NORM_OFFSET;
-       else if (r[0].diff < -RC_PID_NORM_OFFSET)
-               r[0].diff += RC_PID_NORM_OFFSET;
+       if (r[0].diff > norm_offset)
+               r[0].diff -= norm_offset;
+       else if (r[0].diff < -norm_offset)
+               r[0].diff += norm_offset;
        for (i = 0; i < l - 1; i++)
-               if (r[i + 1].diff > r[i].diff + RC_PID_NORM_OFFSET)
-                       r[i + 1].diff -= RC_PID_NORM_OFFSET;
+               if (r[i + 1].diff > r[i].diff + norm_offset)
+                       r[i + 1].diff -= norm_offset;
                else if (r[i + 1].diff <= r[i].diff)
-                       r[i + 1].diff += RC_PID_NORM_OFFSET;
+                       r[i + 1].diff += norm_offset;
 }
 
 static void rate_control_pid_sample(struct rc_pid_info *pinfo,
@@ -163,18 +164,22 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
        struct ieee80211_hw_mode *mode;
        u32 pf;
        s32 err_avg;
-       s32 err_prop;
-       s32 err_int;
-       s32 err_der;
+       u32 err_prop;
+       u32 err_int;
+       u32 err_der;
        int adj, i, j, tmp;
+       unsigned long period;
 
        mode = local->oper_hw_mode;
        spinfo = sta->rate_ctrl_priv;
 
        /* In case nothing happened during the previous control interval, turn
         * the sharpening factor on. */
-       if (jiffies - spinfo->last_sample > 2 * RC_PID_INTERVAL)
-               spinfo->sharp_cnt = RC_PID_SHARPENING_DURATION;
+       period = (HZ * pinfo->sampling_period + 500) / 1000;
+       if (!period)
+               period = 1;
+       if (jiffies - spinfo->last_sample > 2 * period)
+               spinfo->sharp_cnt = pinfo->sharpen_duration;
 
        spinfo->last_sample = jiffies;
 
@@ -202,17 +207,17 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
                rinfo[j].diff = rinfo[i].diff + tmp;
                pinfo->oldrate = sta->txrate;
        }
-       rate_control_pid_normalize(rinfo, mode->num_rates);
+       rate_control_pid_normalize(pinfo, mode->num_rates);
 
        /* Compute the proportional, integral and derivative errors. */
-       err_prop = RC_PID_TARGET_PF - pf;
+       err_prop = pinfo->target - pf;
 
-       err_avg = spinfo->err_avg_sc >> RC_PID_SMOOTHING_SHIFT;
+       err_avg = spinfo->err_avg_sc >> pinfo->smoothing_shift;
        spinfo->err_avg_sc = spinfo->err_avg_sc - err_avg + err_prop;
-       err_int = spinfo->err_avg_sc >> RC_PID_SMOOTHING_SHIFT;
+       err_int = spinfo->err_avg_sc >> pinfo->smoothing_shift;
 
-       err_der = pf - spinfo->last_pf
-                 * (1 + RC_PID_SHARPENING_FACTOR * spinfo->sharp_cnt);
+       err_der = (pf - spinfo->last_pf) *
+                 (1 + pinfo->sharpen_factor * spinfo->sharp_cnt);
        spinfo->last_pf = pf;
        if (spinfo->sharp_cnt)
                        spinfo->sharp_cnt--;
@@ -241,6 +246,7 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
        struct rc_pid_info *pinfo = priv;
        struct sta_info *sta;
        struct rc_pid_sta_info *spinfo;
+       unsigned long period;
 
        sta = sta_info_get(local, hdr->addr1);
 
@@ -285,7 +291,10 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
        sta->tx_num_mpdu_fail += status->retry_count;
 
        /* Update PID controller state. */
-       if (time_after(jiffies, spinfo->last_sample + RC_PID_INTERVAL))
+       period = (HZ * pinfo->sampling_period + 500) / 1000;
+       if (!period)
+               period = 1;
+       if (time_after(jiffies, spinfo->last_sample + period))
                rate_control_pid_sample(pinfo, local, sta);
 
        sta_info_put(sta);
@@ -343,6 +352,9 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local)
        struct ieee80211_hw_mode *mode;
        int i, j, tmp;
        bool s;
+#ifdef CONFIG_MAC80211_DEBUGFS
+       struct rc_pid_debugfs_entries *de;
+#endif
 
        pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC);
        if (!pinfo)
@@ -363,10 +375,10 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local)
        for (i = 0; i < mode->num_rates; i++) {
                rinfo[i].index = i;
                rinfo[i].rev_index = i;
-               if (RC_PID_FAST_START)
+               if (pinfo->fast_start)
                        rinfo[i].diff = 0;
                else
-                       rinfo[i].diff = i * RC_PID_NORM_OFFSET;
+                       rinfo[i].diff = i * pinfo->norm_offset;
        }
        for (i = 1; i < mode->num_rates; i++) {
                s = 0;
@@ -385,18 +397,72 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local)
        }
 
        pinfo->target = RC_PID_TARGET_PF;
+       pinfo->sampling_period = RC_PID_INTERVAL;
        pinfo->coeff_p = RC_PID_COEFF_P;
        pinfo->coeff_i = RC_PID_COEFF_I;
        pinfo->coeff_d = RC_PID_COEFF_D;
+       pinfo->smoothing_shift = RC_PID_SMOOTHING_SHIFT;
+       pinfo->sharpen_factor = RC_PID_SHARPENING_FACTOR;
+       pinfo->sharpen_duration = RC_PID_SHARPENING_DURATION;
+       pinfo->norm_offset = RC_PID_NORM_OFFSET;
+       pinfo->fast_start = RC_PID_FAST_START;
        pinfo->rinfo = rinfo;
        pinfo->oldrate = 0;
 
+#ifdef CONFIG_MAC80211_DEBUGFS
+       de = &pinfo->dentries;
+       de->dir = debugfs_create_dir("rc80211_pid",
+                                    local->hw.wiphy->debugfsdir);
+       de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR,
+                                       de->dir, &pinfo->target);
+       de->sampling_period = debugfs_create_u32("sampling_period",
+                                                S_IRUSR | S_IWUSR, de->dir,
+                                                &pinfo->sampling_period);
+       de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR,
+                                        de->dir, &pinfo->coeff_p);
+       de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR,
+                                        de->dir, &pinfo->coeff_i);
+       de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR,
+                                        de->dir, &pinfo->coeff_d);
+       de->smoothing_shift = debugfs_create_u32("smoothing_shift",
+                                                S_IRUSR | S_IWUSR, de->dir,
+                                                &pinfo->smoothing_shift);
+       de->sharpen_factor = debugfs_create_u32("sharpen_factor",
+                                              S_IRUSR | S_IWUSR, de->dir,
+                                              &pinfo->sharpen_factor);
+       de->sharpen_duration = debugfs_create_u32("sharpen_duration",
+                                                 S_IRUSR | S_IWUSR, de->dir,
+                                                 &pinfo->sharpen_duration);
+       de->norm_offset = debugfs_create_u32("norm_offset",
+                                            S_IRUSR | S_IWUSR, de->dir,
+                                            &pinfo->norm_offset);
+       de->fast_start = debugfs_create_bool("fast_start",
+                                            S_IRUSR | S_IWUSR, de->dir,
+                                            &pinfo->fast_start);
+#endif
+
        return pinfo;
 }
 
 static void rate_control_pid_free(void *priv)
 {
        struct rc_pid_info *pinfo = priv;
+#ifdef CONFIG_MAC80211_DEBUGFS
+       struct rc_pid_debugfs_entries *de = &pinfo->dentries;
+
+       debugfs_remove(de->fast_start);
+       debugfs_remove(de->norm_offset);
+       debugfs_remove(de->sharpen_duration);
+       debugfs_remove(de->sharpen_factor);
+       debugfs_remove(de->smoothing_shift);
+       debugfs_remove(de->coeff_d);
+       debugfs_remove(de->coeff_i);
+       debugfs_remove(de->coeff_p);
+       debugfs_remove(de->sampling_period);
+       debugfs_remove(de->target);
+       debugfs_remove(de->dir);
+#endif
+
        kfree(pinfo->rinfo);
        kfree(pinfo);
 }