]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/wireless/iwlwifi/iwl-3945-rs.c
iwlwifi: handle shared memory Rx index access
[linux-2.6-omap-h63xx.git] / drivers / net / wireless / iwlwifi / iwl-3945-rs.c
index 80d31ae51e774e168a8ed69c60073fad1f708b2d..e51eeeff6992bc8af8a0ea04fdc24401b3f47b17 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2008 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
@@ -29,7 +29,6 @@
 #include <linux/skbuff.h>
 #include <linux/wireless.h>
 #include <net/mac80211.h>
-#include <net/ieee80211.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -37,7 +36,7 @@
 
 #include <linux/workqueue.h>
 
-#include "../net/mac80211/ieee80211_rate.h"
+#include "../net/mac80211/rate.h"
 
 #include "iwl-3945.h"
 
@@ -100,14 +99,6 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = {
        {-89, IWL_RATE_6M_INDEX}
 };
 
-static struct iwl3945_tpt_entry iwl3945_tpt_table_b[] = {
-       {-86, IWL_RATE_11M_INDEX},
-       {-88, IWL_RATE_5M_INDEX},
-       {-90, IWL_RATE_2M_INDEX},
-       {-92, IWL_RATE_1M_INDEX}
-
-};
-
 static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
        {-60, IWL_RATE_54M_INDEX},
        {-64, IWL_RATE_48M_INDEX},
@@ -129,7 +120,7 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
 #define IWL_RATE_MIN_SUCCESS_TH       8
 #define IWL_RATE_DECREASE_TH       1920
 
-static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode)
+static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band)
 {
        u32 index = 0;
        u32 table_size = 0;
@@ -138,21 +129,19 @@ static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode)
        if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL))
                rssi = IWL_MIN_RSSI_VAL;
 
-       switch (mode) {
-       case MODE_IEEE80211G:
+       switch (band) {
+       case IEEE80211_BAND_2GHZ:
                tpt_table = iwl3945_tpt_table_g;
                table_size = ARRAY_SIZE(iwl3945_tpt_table_g);
                break;
 
-       case MODE_IEEE80211A:
+       case IEEE80211_BAND_5GHZ:
                tpt_table = iwl3945_tpt_table_a;
                table_size = ARRAY_SIZE(iwl3945_tpt_table_a);
                break;
 
        default:
-       case MODE_IEEE80211B:
-               tpt_table = iwl3945_tpt_table_b;
-               table_size = ARRAY_SIZE(iwl3945_tpt_table_b);
+               BUG();
                break;
        }
 
@@ -168,9 +157,9 @@ static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window)
 {
        window->data = 0;
        window->success_counter = 0;
-       window->success_ratio = IWL_INVALID_VALUE;
+       window->success_ratio = -1;
        window->counter = 0;
-       window->average_tpt = IWL_INVALID_VALUE;
+       window->average_tpt = IWL_INV_TPT;
        window->stamp = 0;
 }
 
@@ -340,17 +329,17 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
         * after assoc.. */
 
        for (i = IWL_RATE_COUNT - 1; i >= 0; i--) {
-               if (sta->supp_rates & (1 << i)) {
-                       sta->txrate = i;
+               if (sta->supp_rates[local->hw.conf.channel->band] & (1 << i)) {
+                       sta->txrate_idx = i;
                        break;
                }
        }
 
-       sta->last_txrate = sta->txrate;
+       sta->last_txrate_idx = sta->txrate_idx;
 
-       /* For MODE_IEEE80211A mode it start at IWL_FIRST_OFDM_RATE */
-        if (local->hw.conf.phymode == MODE_IEEE80211A)
-                sta->last_txrate += IWL_FIRST_OFDM_RATE;
+       /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
+       if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
+               sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
 
        IWL_DEBUG_RATE("leave\n");
 }
@@ -429,17 +418,19 @@ static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate)
 {
        int next_rate = iwl3945_get_prev_ieee_rate(rate);
 
-       switch (priv->phymode) {
-       case MODE_IEEE80211A:
+       switch (priv->band) {
+       case IEEE80211_BAND_5GHZ:
                if (rate == IWL_RATE_12M_INDEX)
                        next_rate = IWL_RATE_9M_INDEX;
                else if (rate == IWL_RATE_6M_INDEX)
                        next_rate = IWL_RATE_6M_INDEX;
                break;
+/* XXX cannot be invoked in current mac80211 so not a regression
        case MODE_IEEE80211B:
                if (rate == IWL_RATE_11M_INDEX_TABLE)
                        next_rate = IWL_RATE_5M_INDEX_TABLE;
                break;
+ */
        default:
                break;
        }
@@ -465,22 +456,25 @@ static void rs_tx_status(void *priv_rate,
        struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct iwl3945_rs_sta *rs_sta;
+       struct ieee80211_supported_band *sband;
 
        IWL_DEBUG_RATE("enter\n");
 
-       retries = tx_resp->retry_count;
+       sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
 
-       first_index = tx_resp->control.tx_rate;
+
+       retries = tx_resp->retry_count;
+       first_index = tx_resp->control.tx_rate->hw_value;
        if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) {
-               IWL_DEBUG_RATE("leave: Rate out of bounds: %0x for %d\n",
-                              tx_resp->control.tx_rate, first_index);
+               IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index);
                return;
        }
 
+       rcu_read_lock();
+
        sta = sta_info_get(local, hdr->addr1);
        if (!sta || !sta->rate_ctrl_priv) {
-               if (sta)
-                       sta_info_put(sta);
+               rcu_read_unlock();
                IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
                return;
        }
@@ -553,7 +547,7 @@ static void rs_tx_status(void *priv_rate,
 
        spin_unlock_irqrestore(&rs_sta->lock, flags);
 
-       sta_info_put(sta);
+       rcu_read_unlock();
 
        IWL_DEBUG_RATE("leave\n");
 
@@ -561,14 +555,14 @@ static void rs_tx_status(void *priv_rate,
 }
 
 static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
-                                u8 index, u16 rate_mask, int phymode)
+                                u8 index, u16 rate_mask, enum ieee80211_band band)
 {
        u8 high = IWL_RATE_INVALID;
        u8 low = IWL_RATE_INVALID;
 
        /* 802.11A walks to the next literal adjacent rate in
         * the rate table */
-       if (unlikely(phymode == MODE_IEEE80211A)) {
+       if (unlikely(band == IEEE80211_BAND_5GHZ)) {
                int i;
                u32 mask;
 
@@ -639,7 +633,8 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
  *
  */
 static void rs_get_rate(void *priv_rate, struct net_device *dev,
-                       struct ieee80211_hw_mode *mode, struct sk_buff *skb,
+                       struct ieee80211_supported_band *sband,
+                       struct sk_buff *skb,
                        struct rate_selection *sel)
 {
        u8 low = IWL_RATE_INVALID;
@@ -648,9 +643,9 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
        int index;
        struct iwl3945_rs_sta *rs_sta;
        struct iwl3945_rate_scale_data *window = NULL;
-       int current_tpt = IWL_INVALID_VALUE;
-       int low_tpt = IWL_INVALID_VALUE;
-       int high_tpt = IWL_INVALID_VALUE;
+       int current_tpt = IWL_INV_TPT;
+       int low_tpt = IWL_INV_TPT;
+       int high_tpt = IWL_INV_TPT;
        u32 fail_count;
        s8 scale_action = 0;
        unsigned long flags;
@@ -663,6 +658,8 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
 
        IWL_DEBUG_RATE("enter\n");
 
+       rcu_read_lock();
+
        sta = sta_info_get(local, hdr->addr1);
 
        /* Send management frames and broadcast/multicast data using lowest
@@ -672,16 +669,15 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
            is_multicast_ether_addr(hdr->addr1) ||
            !sta || !sta->rate_ctrl_priv) {
                IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
-               sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
-               if (sta)
-                       sta_info_put(sta);
+               sel->rate = rate_lowest(local, sband, sta);
+               rcu_read_unlock();
                return;
        }
 
-       rate_mask = sta->supp_rates;
-       index = min(sta->last_txrate & 0xffff, IWL_RATE_COUNT - 1);
+       rate_mask = sta->supp_rates[sband->band];
+       index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
 
-       if (priv->phymode == (u8) MODE_IEEE80211A)
+       if (sband->band == IEEE80211_BAND_5GHZ)
                rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
 
        rs_sta = (void *)sta->rate_ctrl_priv;
@@ -713,7 +709,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
 
        if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) &&
             (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
-               window->average_tpt = IWL_INVALID_VALUE;
+               window->average_tpt = IWL_INV_TPT;
                spin_unlock_irqrestore(&rs_sta->lock, flags);
 
                IWL_DEBUG_RATE("Invalid average_tpt on rate %d: "
@@ -732,7 +728,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
        current_tpt = window->average_tpt;
 
        high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
-                                        local->hw.conf.phymode);
+                                            sband->band);
        low = high_low & 0xff;
        high = (high_low >> 8) & 0xff;
 
@@ -749,19 +745,16 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
        if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) {
                IWL_DEBUG_RATE("decrease rate because of low success_ratio\n");
                scale_action = -1;
-       } else if ((low_tpt == IWL_INVALID_VALUE) &&
-                  (high_tpt == IWL_INVALID_VALUE))
+       } else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT))
                scale_action = 1;
-       else if ((low_tpt != IWL_INVALID_VALUE) &&
-                  (high_tpt != IWL_INVALID_VALUE)
-                  && (low_tpt < current_tpt)
-                  && (high_tpt < current_tpt)) {
+       else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) &&
+                (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
                IWL_DEBUG_RATE("No action -- low [%d] & high [%d] < "
                               "current_tpt [%d]\n",
                               low_tpt, high_tpt, current_tpt);
                scale_action = 0;
        } else {
-               if (high_tpt != IWL_INVALID_VALUE) {
+               if (high_tpt != IWL_INV_TPT) {
                        if (high_tpt > current_tpt)
                                scale_action = 1;
                        else {
@@ -769,7 +762,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
                                    ("decrease rate because of high tpt\n");
                                scale_action = -1;
                        }
-               } else if (low_tpt != IWL_INVALID_VALUE) {
+               } else if (low_tpt != IWL_INV_TPT) {
                        if (low_tpt > current_tpt) {
                                IWL_DEBUG_RATE
                                    ("decrease rate because of low tpt\n");
@@ -810,17 +803,17 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
 
  out:
 
-       sta->last_txrate = index;
-       if (priv->phymode == (u8) MODE_IEEE80211A)
-               sta->txrate = sta->last_txrate - IWL_FIRST_OFDM_RATE;
+       sta->last_txrate_idx = index;
+       if (sband->band == IEEE80211_BAND_5GHZ)
+               sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE;
        else
-               sta->txrate = sta->last_txrate;
+               sta->txrate_idx = sta->last_txrate_idx;
 
-       sta_info_put(sta);
+       rcu_read_unlock();
 
        IWL_DEBUG_RATE("leave: %d\n", index);
 
-       sel->rate = &priv->ieee_rates[index];
+       sel->rate = &sband->bitrates[sta->txrate_idx];
 }
 
 static struct rate_control_ops rs_ops = {
@@ -848,13 +841,15 @@ int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
        unsigned long now = jiffies;
        u32 max_time = 0;
 
+       rcu_read_lock();
+
        sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
        if (!sta || !sta->rate_ctrl_priv) {
-               if (sta) {
-                       sta_info_put(sta);
+               if (sta)
                        IWL_DEBUG_RATE("leave - no private rate data!\n");
-               else
+               else
                        IWL_DEBUG_RATE("leave - no station!\n");
+               rcu_read_unlock();
                return sprintf(buf, "station %d not found\n", sta_id);
        }
 
@@ -895,7 +890,7 @@ int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
                i = j;
        }
        spin_unlock_irqrestore(&rs_sta->lock, flags);
-       sta_info_put(sta);
+       rcu_read_unlock();
 
        /* Display the average rate of all samples taken.
         *
@@ -932,11 +927,12 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
                return;
        }
 
+       rcu_read_lock();
+
        sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
        if (!sta || !sta->rate_ctrl_priv) {
-               if (sta)
-                       sta_info_put(sta);
                IWL_DEBUG_RATE("leave - no private rate data!\n");
+               rcu_read_unlock();
                return;
        }
 
@@ -945,8 +941,9 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
        spin_lock_irqsave(&rs_sta->lock, flags);
 
        rs_sta->tgg = 0;
-       switch (priv->phymode) {
-       case MODE_IEEE80211G:
+       switch (priv->band) {
+       case IEEE80211_BAND_2GHZ:
+               /* TODO: this always does G, not a regression */
                if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
                        rs_sta->tgg = 1;
                        rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
@@ -954,18 +951,15 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
                        rs_sta->expected_tpt = iwl3945_expected_tpt_g;
                break;
 
-       case MODE_IEEE80211A:
+       case IEEE80211_BAND_5GHZ:
                rs_sta->expected_tpt = iwl3945_expected_tpt_a;
                break;
-
-       default:
-               IWL_WARNING("Invalid phymode.  Defaulting to 802.11b\n");
-       case MODE_IEEE80211B:
-               rs_sta->expected_tpt = iwl3945_expected_tpt_b;
+       case IEEE80211_NUM_BANDS:
+               BUG();
                break;
        }
 
-       sta_info_put(sta);
+       rcu_read_unlock();
        spin_unlock_irqrestore(&rs_sta->lock, flags);
 
        rssi = priv->last_rx_rssi;
@@ -974,20 +968,19 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
 
        IWL_DEBUG(IWL_DL_INFO | IWL_DL_RATE, "Network RSSI: %d\n", rssi);
 
-       rs_sta->start_rate =
-                       iwl3945_get_rate_index_by_rssi(rssi, priv->phymode);
+       rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
 
        IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
                       "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
                       iwl3945_rates[rs_sta->start_rate].plcp);
 }
 
-void iwl3945_rate_control_register(struct ieee80211_hw *hw)
+int iwl3945_rate_control_register(void)
 {
-       ieee80211_rate_control_register(&rs_ops);
+       return ieee80211_rate_control_register(&rs_ops);
 }
 
-void iwl3945_rate_control_unregister(struct ieee80211_hw *hw)
+void iwl3945_rate_control_unregister(void)
 {
        ieee80211_rate_control_unregister(&rs_ops);
 }