iwlwifi: allow user to set max rate
authorAbbas, Mohamed <mohamed.abbas@intel.com>
Wed, 21 Jan 2009 05:33:52 +0000 (21:33 -0800)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 29 Jan 2009 21:01:04 +0000 (16:01 -0500)
allow user to set max rate through #iwconfig <inteface> rate XXX.
mac80211 will try to force this if user set it, but driver is not
in sync which cause mac80211 to report wrong current rate. This
patch will check if max rate is set and force it in rate scaling

Signed-off-by: mohamed abbas <mohamed.abbas@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwlwifi/iwl-3945-rs.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.c

index 25b4356fcc1c106e5aee927a65aa77ecd1ed56ee..044abf734eb610ea60c084574095403dab45d080 100644 (file)
@@ -651,6 +651,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        u16 fc;
        u16 rate_mask = 0;
+       s8 max_rate_idx = -1;
        struct iwl_priv *priv = (struct iwl_priv *)priv_r;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
@@ -675,6 +676,13 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
                return;
        }
 
+       /* get user max rate if set */
+       max_rate_idx = txrc->max_rate_idx;
+       if ((sband->band == IEEE80211_BAND_5GHZ) && (max_rate_idx != -1))
+               max_rate_idx += IWL_FIRST_OFDM_RATE;
+       if ((max_rate_idx < 0) || (max_rate_idx >= IWL_RATE_COUNT))
+               max_rate_idx = -1;
+
        index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1);
 
        if (sband->band == IEEE80211_BAND_5GHZ)
@@ -706,6 +714,12 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
                rs_sta->start_rate = IWL_RATE_INVALID;
        }
 
+       /* force user max rate if set by user */
+       if ((max_rate_idx != -1) && (max_rate_idx < index)) {
+               if (rate_mask & (1 << max_rate_idx))
+                       index = max_rate_idx;
+       }
+
        window = &(rs_sta->win[index]);
 
        fail_count = window->counter - window->success_counter;
@@ -732,6 +746,10 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
        low = high_low & 0xff;
        high = (high_low >> 8) & 0xff;
 
+       /* If user set max rate, dont allow higher than user constrain */
+       if ((max_rate_idx != -1) && (max_rate_idx < high))
+               high = IWL_RATE_INVALID;
+
        if (low != IWL_RATE_INVALID)
                low_tpt = rs_sta->win[low].average_tpt;
 
index a82cce5fbff815158137ce1896ae65f014be2da5..12c5e5d6e910dbf48efc278604fde0982fcee6d3 100644 (file)
@@ -148,6 +148,7 @@ struct iwl_lq_sta {
        u16 active_mimo2_rate;
        u16 active_mimo3_rate;
        u16 active_rate_basic;
+       s8 max_rate_idx;     /* Max rate set by user */
 
        struct iwl_link_quality_cmd lq;
        struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
@@ -1759,6 +1760,15 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
                return;
        }
 
+       /* force user max rate if set by user */
+       if ((lq_sta->max_rate_idx != -1) &&
+           (lq_sta->max_rate_idx < index)) {
+               index = lq_sta->max_rate_idx;
+               update_lq = 1;
+               window = &(tbl->win[index]);
+               goto lq_update;
+       }
+
        window = &(tbl->win[index]);
 
        /*
@@ -1850,6 +1860,11 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
        low = high_low & 0xff;
        high = (high_low >> 8) & 0xff;
 
+       /* If user set max rate, dont allow higher than user constrain */
+       if ((lq_sta->max_rate_idx != -1) &&
+           (lq_sta->max_rate_idx < high))
+               high = IWL_RATE_INVALID;
+
        sr = window->success_ratio;
 
        /* Collect measured throughputs for current and adjacent rates */
@@ -2110,6 +2125,17 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
 
        IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
 
+       /* Get max rate if user set max rate */
+       if (lq_sta) {
+               lq_sta->max_rate_idx = txrc->max_rate_idx;
+               if ((sband->band == IEEE80211_BAND_5GHZ) &&
+                   (lq_sta->max_rate_idx != -1))
+                       lq_sta->max_rate_idx += IWL_FIRST_OFDM_RATE;
+               if ((lq_sta->max_rate_idx < 0) ||
+                   (lq_sta->max_rate_idx >= IWL_RATE_COUNT))
+                       lq_sta->max_rate_idx = -1;
+       }
+
        if (sta)
                mask_bit = sta->supp_rates[sband->band];
 
@@ -2220,6 +2246,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
        }
 
        lq_sta->is_dup = 0;
+       lq_sta->max_rate_idx = -1;
        lq_sta->is_green = rs_use_green(priv, conf);
        lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
        lq_sta->active_rate_basic = priv->active_rate_basic;