]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/iwlwifi/iwl-agn-rs.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[karo-tx-linux.git] / drivers / net / wireless / iwlwifi / iwl-agn-rs.c
index be00cb3b1d0e86557a28404296b1b9ef71a4a0c7..0c3c76803c5e7227237d1a619ef6a2e2f0374df7 100644 (file)
@@ -610,10 +610,6 @@ static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta,
                                  struct ieee80211_hdr *hdr,
                                  enum iwl_table_type rate_type)
 {
-       if (hdr && is_multicast_ether_addr(hdr->addr1) &&
-           lq_sta->active_rate_basic)
-               return lq_sta->active_rate_basic;
-
        if (is_legacy(rate_type)) {
                return lq_sta->active_legacy_rate;
        } else {
@@ -774,6 +770,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
 
        IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");
 
+       /* Treat uninitialized rate scaling data same as non-existing. */
+       if (!lq_sta) {
+               IWL_DEBUG_RATE(priv, "Station rate scaling not created yet.\n");
+               return;
+       } else if (!lq_sta->drv) {
+               IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n");
+               return;
+       }
+
        if (!ieee80211_is_data(hdr->frame_control) ||
            info->flags & IEEE80211_TX_CTL_NO_ACK)
                return;
@@ -783,10 +788,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
            !(info->flags & IEEE80211_TX_STAT_AMPDU))
                return;
 
-       if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
-           !lq_sta->ibss_sta_added)
-               return;
-
        /*
         * Ignore this Tx frame response if its initial rate doesn't match
         * that of latest Link Quality command.  There may be stragglers
@@ -832,7 +833,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
                lq_sta->missed_rate_counter++;
                if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
                        lq_sta->missed_rate_counter = 0;
-                       iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+                       iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
                }
                /* Regardless, ignore this status info for outdated rate */
                return;
@@ -1912,7 +1913,7 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv,
        /* Update uCode's rate table. */
        rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
        rs_fill_link_cmd(priv, lq_sta, rate);
-       iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+       iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
 
        return rate;
 }
@@ -2001,7 +2002,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
        /* rates available for this association, and for modulation mode */
        rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type);
 
-       IWL_DEBUG_RATE(priv, "mask 0x%04X \n", rate_mask);
+       IWL_DEBUG_RATE(priv, "mask 0x%04X\n", rate_mask);
 
        /* mask with station rate restriction */
        if (is_legacy(tbl->lq_type)) {
@@ -2288,7 +2289,7 @@ lq_update:
                        IWL_DEBUG_RATE(priv, "Switch current  mcs: %X index: %d\n",
                                     tbl->current_rate, index);
                        rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
-                       iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+                       iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false);
                } else
                        done_search = 1;
        }
@@ -2337,7 +2338,20 @@ out:
        return;
 }
 
-
+/**
+ * rs_initialize_lq - Initialize a station's hardware rate table
+ *
+ * The uCode's station table contains a table of fallback rates
+ * for automatic fallback during transmission.
+ *
+ * NOTE: This sets up a default set of values.  These will be replaced later
+ *       if the driver's iwl-agn-rs rate scaling algorithm is used, instead of
+ *       rc80211_simple.
+ *
+ * NOTE: Run REPLY_ADD_STA command to set up station table entry, before
+ *       calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
+ *       which requires station table entry to exist).
+ */
 static void rs_initialize_lq(struct iwl_priv *priv,
                             struct ieee80211_conf *conf,
                             struct ieee80211_sta *sta,
@@ -2356,10 +2370,6 @@ static void rs_initialize_lq(struct iwl_priv *priv,
 
        i = lq_sta->last_txrate_idx;
 
-       if ((lq_sta->lq.sta_id == 0xff) &&
-           (priv->iw_mode == NL80211_IFTYPE_ADHOC))
-               goto out;
-
        valid_tx_ant = priv->hw_params.valid_tx_ant;
 
        if (!lq_sta->search_better_tbl)
@@ -2387,7 +2397,8 @@ static void rs_initialize_lq(struct iwl_priv *priv,
        tbl->current_rate = rate;
        rs_set_expected_tpt_table(lq_sta, tbl);
        rs_fill_link_cmd(NULL, lq_sta, rate);
-       iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+       priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq;
+       iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_SYNC, true);
  out:
        return;
 }
@@ -2399,9 +2410,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
        struct sk_buff *skb = txrc->skb;
        struct ieee80211_supported_band *sband = txrc->sband;
        struct iwl_priv *priv = (struct iwl_priv *)priv_r;
-       struct ieee80211_conf *conf = &priv->hw->conf;
-       struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct iwl_lq_sta *lq_sta = priv_sta;
        int rate_idx;
@@ -2419,30 +2427,18 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
                        lq_sta->max_rate_idx = -1;
        }
 
+       /* Treat uninitialized rate scaling data same as non-existing. */
+       if (lq_sta && !lq_sta->drv) {
+               IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n");
+               priv_sta = NULL;
+       }
+
        /* Send management frames and NO_ACK data using lowest rate. */
        if (rate_control_send_low(sta, priv_sta, txrc))
                return;
 
        rate_idx  = lq_sta->last_txrate_idx;
 
-       if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
-           !lq_sta->ibss_sta_added) {
-               u8 sta_id = iwl_find_station(priv, hdr->addr1);
-
-               if (sta_id == IWL_INVALID_STATION) {
-                       IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n",
-                                      hdr->addr1);
-                       sta_id = iwl_add_station(priv, hdr->addr1,
-                                               false, CMD_ASYNC, ht_cap);
-               }
-               if ((sta_id != IWL_INVALID_STATION)) {
-                       lq_sta->lq.sta_id = sta_id;
-                       lq_sta->lq.rs_table[0].rate_n_flags = 0;
-                       lq_sta->ibss_sta_added = 1;
-                       rs_initialize_lq(priv, conf, sta, lq_sta);
-               }
-       }
-
        if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) {
                rate_idx -= IWL_FIRST_OFDM_RATE;
                /* 6M and 9M shared same MCS index */
@@ -2492,16 +2488,25 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
        return lq_sta;
 }
 
-static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
-                        struct ieee80211_sta *sta, void *priv_sta)
+/*
+ * Called after adding a new station to initialize rate scaling
+ */
+void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id)
 {
        int i, j;
-       struct iwl_priv *priv = (struct iwl_priv *)priv_r;
+       struct ieee80211_hw *hw = priv->hw;
        struct ieee80211_conf *conf = &priv->hw->conf;
        struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
-       struct iwl_lq_sta *lq_sta = priv_sta;
+       struct iwl_station_priv *sta_priv;
+       struct iwl_lq_sta *lq_sta;
+       struct ieee80211_supported_band *sband;
+
+       sta_priv = (struct iwl_station_priv *) sta->drv_priv;
+       lq_sta = &sta_priv->lq_sta;
+       sband = hw->wiphy->bands[conf->channel->band];
+
 
-       lq_sta->lq.sta_id = 0xff;
+       lq_sta->lq.sta_id = sta_id;
 
        for (j = 0; j < LQ_SIZE; j++)
                for (i = 0; i < IWL_RATE_COUNT; i++)
@@ -2513,39 +2518,18 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
                for (i = 0; i < IWL_RATE_COUNT; i++)
                        rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
 
-       IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init ***\n");
+       IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init for station %d ***\n",
+                      sta_id);
        /* TODO: what is a good starting rate for STA? About middle? Maybe not
         * the lowest or the highest rate.. Could consider using RSSI from
         * previous packets? Need to have IEEE 802.1X auth succeed immediately
         * after assoc.. */
 
-       lq_sta->ibss_sta_added = 0;
-       if (priv->iw_mode == NL80211_IFTYPE_AP) {
-               u8 sta_id = iwl_find_station(priv,
-                                                               sta->addr);
-
-               /* for IBSS the call are from tasklet */
-               IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr);
-
-               if (sta_id == IWL_INVALID_STATION) {
-                       IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr);
-                       sta_id = iwl_add_station(priv, sta->addr, false,
-                                               CMD_ASYNC, ht_cap);
-               }
-               if ((sta_id != IWL_INVALID_STATION)) {
-                       lq_sta->lq.sta_id = sta_id;
-                       lq_sta->lq.rs_table[0].rate_n_flags = 0;
-               }
-               /* FIXME: this is w/a remove it later */
-               priv->assoc_station_added = 1;
-       }
-
        lq_sta->is_dup = 0;
        lq_sta->max_rate_idx = -1;
        lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
        lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config);
        lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
-       lq_sta->active_rate_basic = priv->active_rate_basic;
        lq_sta->band = priv->band;
        /*
         * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
@@ -2793,7 +2777,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
 
        if (lq_sta->dbg_fixed_rate) {
                rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
-               iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC);
+               iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false);
        }
 
        return count;
@@ -2949,12 +2933,6 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
                desc += sprintf(buff+desc,
                                "Bit Rate= %d Mb/s\n",
                                iwl_rates[lq_sta->last_txrate_idx].ieee >> 1);
-       desc += sprintf(buff+desc,
-                       "Signal Level= %d dBm\tNoise Level= %d dBm\n",
-                       priv->last_rx_rssi, priv->last_rx_noise);
-       desc += sprintf(buff+desc,
-                       "Tsf= 0x%llx\tBeacon time= 0x%08X\n",
-                       priv->last_tsf, priv->last_beacon_time);
 
        ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
        return ret;
@@ -2994,12 +2972,21 @@ static void rs_remove_debugfs(void *priv, void *priv_sta)
 }
 #endif
 
+/*
+ * Initialization of rate scaling information is done by driver after
+ * the station is added. Since mac80211 calls this function before a
+ * station is added we ignore it.
+ */
+static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband,
+                        struct ieee80211_sta *sta, void *priv_sta)
+{
+}
 static struct rate_control_ops rs_ops = {
        .module = NULL,
        .name = RS_NAME,
        .tx_status = rs_tx_status,
        .get_rate = rs_get_rate,
-       .rate_init = rs_rate_init,
+       .rate_init = rs_rate_init_stub,
        .alloc = rs_alloc,
        .free = rs_free,
        .alloc_sta = rs_alloc_sta,