Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[safe/jmp/linux-2.6] / drivers / net / wireless / iwlwifi / iwl-agn-rs.c
index 2d4ec1a..be00cb3 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -150,7 +150,7 @@ static s32 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = {
 };
 
 /* mbps, mcs */
-const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
+static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
        {  "1", "BPSK DSSS"},
        {  "2", "QPSK DSSS"},
        {"5.5", "BPSK CCK"},
@@ -298,10 +298,23 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
                                      struct iwl_lq_sta *lq_data, u8 tid,
                                      struct ieee80211_sta *sta)
 {
+       int ret;
+
        if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
                IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
                                sta->addr, tid);
-               ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid);
+               ret = ieee80211_start_tx_ba_session(sta, tid);
+               if (ret == -EAGAIN) {
+                       /*
+                        * driver and mac80211 is out of sync
+                        * this might be cause by reloading firmware
+                        * stop the tx ba session here
+                        */
+                       IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n",
+                               tid);
+                       ret = ieee80211_stop_tx_ba_session(sta, tid,
+                                               WLAN_BACK_INITIATOR);
+               }
        }
 }
 
@@ -332,6 +345,17 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
               !!(rate_n_flags & RATE_MCS_ANT_C_MSK);
 }
 
+/*
+ * Static function to get the expected throughput from an iwl_scale_tbl_info
+ * that wraps a NULL pointer check
+ */
+static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)
+{
+       if (tbl->expected_tpt)
+               return tbl->expected_tpt[rs_index];
+       return 0;
+}
+
 /**
  * rs_collect_tx_data - Update the success/failure sliding window
  *
@@ -339,19 +363,21 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
  * at this rate.  window->data contains the bitmask of successful
  * packets.
  */
-static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
-                             int scale_index, s32 tpt, int attempts,
-                             int successes)
+static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl,
+                             int scale_index, int attempts, int successes)
 {
        struct iwl_rate_scale_data *window = NULL;
        static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1));
-       s32 fail_count;
+       s32 fail_count, tpt;
 
        if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)
                return -EINVAL;
 
        /* Select window for current tx bit rate */
-       window = &(windows[scale_index]);
+       window = &(tbl->win[scale_index]);
+
+       /* Get expected throughput */
+       tpt = get_expected_tpt(tbl, scale_index);
 
        /*
         * Keep track of only the latest 62 tx frame attempts in this rate's
@@ -725,16 +751,6 @@ static bool table_type_matches(struct iwl_scale_tbl_info *a,
        return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) &&
                (a->is_SGI == b->is_SGI);
 }
-/*
- * Static function to get the expected throughput from an iwl_scale_tbl_info
- * that wraps a NULL pointer check
- */
-static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)
-{
-       if (tbl->expected_tpt)
-               return tbl->expected_tpt[rs_index];
-       return 0;
-}
 
 /*
  * mac80211 sends us Tx status
@@ -751,12 +767,10 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        struct iwl_priv *priv = (struct iwl_priv *)priv_r;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct iwl_rate_scale_data *window = NULL;
        enum mac80211_rate_control_flags mac_flags;
        u32 tx_rate;
        struct iwl_scale_tbl_info tbl_type;
-       struct iwl_scale_tbl_info *curr_tbl, *other_tbl;
-       s32 tpt = 0;
+       struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
 
        IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");
 
@@ -839,7 +853,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
                IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n");
                return;
        }
-       window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]);
 
        /*
         * Updating the frame history depends on whether packets were
@@ -852,8 +865,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
                tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
                rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type,
                                &rs_index);
-               tpt = get_expected_tpt(curr_tbl, rs_index);
-               rs_collect_tx_data(window, rs_index, tpt,
+               rs_collect_tx_data(curr_tbl, rs_index,
                                   info->status.ampdu_ack_len,
                                   info->status.ampdu_ack_map);
 
@@ -883,19 +895,13 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
                         * table as active/search.
                         */
                        if (table_type_matches(&tbl_type, curr_tbl))
-                               tpt = get_expected_tpt(curr_tbl, rs_index);
+                               tmp_tbl = curr_tbl;
                        else if (table_type_matches(&tbl_type, other_tbl))
-                               tpt = get_expected_tpt(other_tbl, rs_index);
+                               tmp_tbl = other_tbl;
                        else
                                continue;
-
-                       /* Constants mean 1 transmission, 0 successes */
-                       if (i < retries)
-                               rs_collect_tx_data(window, rs_index, tpt, 1,
-                                               0);
-                       else
-                               rs_collect_tx_data(window, rs_index, tpt, 1,
-                                               legacy_success);
+                       rs_collect_tx_data(tmp_tbl, rs_index, 1,
+                                          i < retries ? 0 : legacy_success);
                }
 
                /* Update success/fail counts if not searching for new mode */
@@ -2475,22 +2481,13 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
                          gfp_t gfp)
 {
        struct iwl_lq_sta *lq_sta;
+       struct iwl_station_priv *sta_priv = (struct iwl_station_priv *) sta->drv_priv;
        struct iwl_priv *priv;
-       int i, j;
 
        priv = (struct iwl_priv *)priv_rate;
        IWL_DEBUG_RATE(priv, "create station rate scale window\n");
 
-       lq_sta = kzalloc(sizeof(struct iwl_lq_sta), gfp);
-
-       if (lq_sta == NULL)
-               return NULL;
-       lq_sta->lq.sta_id = 0xff;
-
-
-       for (j = 0; j < LQ_SIZE; j++)
-               for (i = 0; i < IWL_RATE_COUNT; i++)
-                       rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
+       lq_sta = &sta_priv->lq_sta;
 
        return lq_sta;
 }
@@ -2504,6 +2501,12 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
        struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
        struct iwl_lq_sta *lq_sta = priv_sta;
 
+       lq_sta->lq.sta_id = 0xff;
+
+       for (j = 0; j < LQ_SIZE; j++)
+               for (i = 0; i < IWL_RATE_COUNT; i++)
+                       rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
+
        lq_sta->flush_timer = 0;
        lq_sta->supp_rates = sta->supp_rates[sband->band];
        for (j = 0; j < LQ_SIZE; j++)
@@ -2719,11 +2722,9 @@ static void rs_free(void *priv_rate)
 static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta,
                        void *priv_sta)
 {
-       struct iwl_lq_sta *lq_sta = priv_sta;
        struct iwl_priv *priv __maybe_unused = priv_r;
 
        IWL_DEBUG_RATE(priv, "enter\n");
-       kfree(lq_sta);
        IWL_DEBUG_RATE(priv, "leave\n");
 }
 
@@ -2969,16 +2970,16 @@ static void rs_add_debugfs(void *priv, void *priv_sta,
 {
        struct iwl_lq_sta *lq_sta = priv_sta;
        lq_sta->rs_sta_dbgfs_scale_table_file =
-               debugfs_create_file("rate_scale_table", 0600, dir,
+               debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir,
                                lq_sta, &rs_sta_dbgfs_scale_table_ops);
        lq_sta->rs_sta_dbgfs_stats_table_file =
-               debugfs_create_file("rate_stats_table", 0600, dir,
+               debugfs_create_file("rate_stats_table", S_IRUSR, dir,
                        lq_sta, &rs_sta_dbgfs_stats_table_ops);
        lq_sta->rs_sta_dbgfs_rate_scale_data_file =
-               debugfs_create_file("rate_scale_data", 0600, dir,
+               debugfs_create_file("rate_scale_data", S_IRUSR, dir,
                        lq_sta, &rs_sta_dbgfs_rate_scale_data_ops);
        lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
-               debugfs_create_u8("tx_agg_tid_enable", 0600, dir,
+               debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir,
                &lq_sta->tx_agg_tid_en);
 
 }