]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/iwlwifi/iwl-sta.c
iwlwifi: fix printk newlines
[linux-2.6] / drivers / net / wireless / iwlwifi / iwl-sta.c
index 983f10760fb06e686344e079371d089c7e062fb2..6283a3a707f58dad2f5cb17bfcb82ed05a57a148 100644 (file)
 #include <net/mac80211.h>
 #include <linux/etherdevice.h>
 
-#include "iwl-eeprom.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-sta.h"
-#include "iwl-io.h"
 #include "iwl-helpers.h"
 
 
-#define IWL_STA_DRIVER_ACTIVE          0x1     /* ucode entry is active */
-#define IWL_STA_UCODE_ACTIVE           0x2     /* ucode entry is active */
+#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */
+#define IWL_STA_UCODE_ACTIVE  BIT(1) /* ucode entry is active */
 
 u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
 {
@@ -74,10 +72,39 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
 }
 EXPORT_SYMBOL(iwl_find_station);
 
+int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
+{
+       if (priv->iw_mode == IEEE80211_IF_TYPE_STA) {
+               return IWL_AP_ID;
+       } else {
+               u8 *da = ieee80211_get_DA(hdr);
+               return iwl_find_station(priv, da);
+       }
+}
+EXPORT_SYMBOL(iwl_get_ra_sta_id);
+
+static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
+{
+       unsigned long flags;
+       DECLARE_MAC_BUF(mac);
+
+       spin_lock_irqsave(&priv->sta_lock, flags);
+
+       if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
+               IWL_ERROR("ACTIVATE a non DRIVER active station %d\n", sta_id);
+
+       priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
+       IWL_DEBUG_ASSOC("Added STA to Ucode: %s\n",
+                       print_mac(mac, priv->stations[sta_id].sta.sta.addr));
+
+       spin_unlock_irqrestore(&priv->sta_lock, flags);
+}
+
 static int iwl_add_sta_callback(struct iwl_priv *priv,
                                   struct iwl_cmd *cmd, struct sk_buff *skb)
 {
        struct iwl_rx_packet *res = NULL;
+       u8 sta_id = cmd->cmd.addsta.sta.sta_id;
 
        if (!skb) {
                IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n");
@@ -93,8 +120,8 @@ static int iwl_add_sta_callback(struct iwl_priv *priv,
 
        switch (res->u.add_sta.status) {
        case ADD_STA_SUCCESS_MSK:
-               /* FIXME: implement iwl_sta_ucode_activate(priv, addr); */
-               /* fail through */
+               iwl_sta_ucode_activate(priv, sta_id);
+                /* fall through */
        default:
                IWL_DEBUG_HC("Received REPLY_ADD_STA:(0x%08X)\n",
                             res->u.add_sta.status);
@@ -105,8 +132,6 @@ static int iwl_add_sta_callback(struct iwl_priv *priv,
        return 1;
 }
 
-
-
 int iwl_send_add_sta(struct iwl_priv *priv,
                     struct iwl_addsta_cmd *sta, u8 flags)
 {
@@ -140,6 +165,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
        if (ret == 0) {
                switch (res->u.add_sta.status) {
                case ADD_STA_SUCCESS_MSK:
+                       iwl_sta_ucode_activate(priv, sta->sta.sta_id);
                        IWL_DEBUG_INFO("REPLY_ADD_STA PASSED\n");
                        break;
                default:
@@ -156,8 +182,6 @@ int iwl_send_add_sta(struct iwl_priv *priv,
 }
 EXPORT_SYMBOL(iwl_send_add_sta);
 
-#ifdef CONFIG_IWL4965_HT
-
 static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
                                   struct ieee80211_ht_info *sta_ht_inf)
 {
@@ -183,7 +207,7 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
        case WLAN_HT_CAP_MIMO_PS_DISABLED:
                break;
        default:
-               IWL_WARNING("Invalid MIMO PS mode %d", mimo_ps_mode);
+               IWL_WARNING("Invalid MIMO PS mode %d\n", mimo_ps_mode);
                break;
        }
 
@@ -202,12 +226,6 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
  done:
        return;
 }
-#else
-static inline void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
-                                       struct ieee80211_ht_info *sta_ht_info)
-{
-}
-#endif
 
 /**
  * iwl_add_station_flags - Add station to tables in driver and device
@@ -216,89 +234,92 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
                         u8 flags, struct ieee80211_ht_info *ht_info)
 {
        int i;
-       int index = IWL_INVALID_STATION;
+       int sta_id = IWL_INVALID_STATION;
        struct iwl_station_entry *station;
        unsigned long flags_spin;
        DECLARE_MAC_BUF(mac);
 
        spin_lock_irqsave(&priv->sta_lock, flags_spin);
        if (is_ap)
-               index = IWL_AP_ID;
+               sta_id = IWL_AP_ID;
        else if (is_broadcast_ether_addr(addr))
-               index = priv->hw_params.bcast_sta_id;
+               sta_id = priv->hw_params.bcast_sta_id;
        else
                for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
                        if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
                                                addr)) {
-                               index = i;
+                               sta_id = i;
                                break;
                        }
 
                        if (!priv->stations[i].used &&
-                           index == IWL_INVALID_STATION)
-                               index = i;
+                           sta_id == IWL_INVALID_STATION)
+                               sta_id = i;
                }
 
-
        /* These two conditions have the same outcome, but keep them separate
-         since they have different meanings */
-       if (unlikely(index == IWL_INVALID_STATION)) {
+          since they have different meanings */
+       if (unlikely(sta_id == IWL_INVALID_STATION)) {
                spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-               return index;
+               return sta_id;
        }
 
-       if (priv->stations[index].used &&
-           !compare_ether_addr(priv->stations[index].sta.sta.addr, addr)) {
+       if (priv->stations[sta_id].used &&
+           !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) {
                spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-               return index;
+               return sta_id;
        }
 
 
-       IWL_DEBUG_ASSOC("Add STA ID %d: %s\n", index, print_mac(mac, addr));
-       station = &priv->stations[index];
-       station->used = 1;
+       station = &priv->stations[sta_id];
+       station->used = IWL_STA_DRIVER_ACTIVE;
+       IWL_DEBUG_ASSOC("Add STA to driver ID %d: %s\n",
+                       sta_id, print_mac(mac, addr));
        priv->num_stations++;
 
        /* Set up the REPLY_ADD_STA command to send to device */
        memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
        memcpy(station->sta.sta.addr, addr, ETH_ALEN);
        station->sta.mode = 0;
-       station->sta.sta.sta_id = index;
+       station->sta.sta.sta_id = sta_id;
        station->sta.station_flags = 0;
 
        /* BCAST station and IBSS stations do not work in HT mode */
-       if (index != priv->hw_params.bcast_sta_id &&
+       if (sta_id != priv->hw_params.bcast_sta_id &&
            priv->iw_mode != IEEE80211_IF_TYPE_IBSS)
-               iwl_set_ht_add_station(priv, index, ht_info);
+               iwl_set_ht_add_station(priv, sta_id, ht_info);
 
        spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
 
        /* Add station to device's station table */
        iwl_send_add_sta(priv, &station->sta, flags);
-       return index;
+       return sta_id;
 
 }
 EXPORT_SYMBOL(iwl_add_station_flags);
 
-
-static int iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
+static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
 {
        unsigned long flags;
-       u8 sta_id;
        DECLARE_MAC_BUF(mac);
 
-       sta_id = iwl_find_station(priv, addr);
-       if (sta_id != IWL_INVALID_STATION) {
-               IWL_DEBUG_ASSOC("Removed STA from Ucode: %s\n",
-                               print_mac(mac, addr));
-               spin_lock_irqsave(&priv->sta_lock, flags);
-               priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
-               memset(&priv->stations[sta_id], 0,
-                       sizeof(struct iwl_station_entry));
-               spin_unlock_irqrestore(&priv->sta_lock, flags);
-               return 0;
-       }
-       return -EINVAL;
+       u8 sta_id = iwl_find_station(priv, addr);
+
+       BUG_ON(sta_id == IWL_INVALID_STATION);
+
+       IWL_DEBUG_ASSOC("Removed STA from Ucode: %s\n",
+                       print_mac(mac, addr));
+
+       spin_lock_irqsave(&priv->sta_lock, flags);
+
+       /* Ucode must be active and driver must be non active */
+       if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE)
+               IWL_ERROR("removed non active STA %d\n", sta_id);
+
+       priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
+
+       memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry));
+       spin_unlock_irqrestore(&priv->sta_lock, flags);
 }
 
 static int iwl_remove_sta_callback(struct iwl_priv *priv,
@@ -324,6 +345,7 @@ static int iwl_remove_sta_callback(struct iwl_priv *priv,
                iwl_sta_ucode_deactivate(priv, addr);
                break;
        default:
+               IWL_ERROR("REPLY_REMOVE_STA failed\n");
                break;
        }
 
@@ -384,49 +406,68 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
 
        return ret;
 }
+
 /**
  * iwl_remove_station - Remove driver's knowledge of station.
- *
  */
-u8 iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
+int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
 {
-       int index = IWL_INVALID_STATION;
-       int i;
+       int sta_id = IWL_INVALID_STATION;
+       int i, ret = -EINVAL;
        unsigned long flags;
+       DECLARE_MAC_BUF(mac);
 
        spin_lock_irqsave(&priv->sta_lock, flags);
 
        if (is_ap)
-               index = IWL_AP_ID;
+               sta_id = IWL_AP_ID;
        else if (is_broadcast_ether_addr(addr))
-               index = priv->hw_params.bcast_sta_id;
+               sta_id = priv->hw_params.bcast_sta_id;
        else
                for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
                        if (priv->stations[i].used &&
                            !compare_ether_addr(priv->stations[i].sta.sta.addr,
                                                addr)) {
-                               index = i;
+                               sta_id = i;
                                break;
                        }
 
-       if (unlikely(index == IWL_INVALID_STATION))
+       if (unlikely(sta_id == IWL_INVALID_STATION))
                goto out;
 
-       if (priv->stations[index].used) {
-               priv->stations[index].used = 0;
-               priv->num_stations--;
+       IWL_DEBUG_ASSOC("Removing STA from driver:%d  %s\n",
+               sta_id, print_mac(mac, addr));
+
+       if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+               IWL_ERROR("Removing %s but non DRIVER active\n",
+                               print_mac(mac, addr));
+               goto out;
+       }
+
+       if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
+               IWL_ERROR("Removing %s but non UCODE active\n",
+                               print_mac(mac, addr));
+               goto out;
        }
 
+
+       priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+
+       priv->num_stations--;
+
        BUG_ON(priv->num_stations < 0);
+
        spin_unlock_irqrestore(&priv->sta_lock, flags);
-       iwl_send_remove_station(priv, addr, CMD_ASYNC);
-       return index;
+
+       ret = iwl_send_remove_station(priv, addr, CMD_ASYNC);
+       return ret;
 out:
        spin_unlock_irqrestore(&priv->sta_lock, flags);
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL(iwl_remove_station);
-int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
+
+static int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
 {
        int i;
 
@@ -496,6 +537,8 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
        priv->default_wep_key--;
        memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
        ret = iwl_send_static_wepkey_cmd(priv, 1);
+       IWL_DEBUG_WEP("Remove default WEP key: idx=%d ret=%d\n",
+                     keyconf->keyidx, ret);
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 
        return ret;
@@ -508,6 +551,12 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
        int ret;
        unsigned long flags;
 
+       if (keyconf->keylen != WEP_KEY_LEN_128 &&
+           keyconf->keylen != WEP_KEY_LEN_64) {
+               IWL_DEBUG_WEP("Bad WEP key length %d\n", keyconf->keylen);
+               return -EINVAL;
+       }
+
        keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
        keyconf->hw_key_idx = HW_KEY_DEFAULT;
        priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP;
@@ -524,6 +573,8 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
                                                        keyconf->keylen);
 
        ret = iwl_send_static_wepkey_cmd(priv, 0);
+       IWL_DEBUG_WEP("Set default WEP key: len=%d idx=%d ret=%d\n",
+               keyconf->keylen, keyconf->keyidx, ret);
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 
        return ret;
@@ -670,6 +721,9 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
        key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
        keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
 
+       IWL_DEBUG_WEP("Remove dynamic key: idx=%d sta=%d\n",
+                     keyconf->keyidx, sta_id);
+
        if (keyconf->keyidx != keyidx) {
                /* We need to remove a key with index different that the one
                 * in the uCode. This means that the key we need to remove has
@@ -694,7 +748,6 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
        priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
        priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 
-       IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
        ret =  iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
        spin_unlock_irqrestore(&priv->sta_lock, flags);
        return ret;
@@ -724,6 +777,10 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
                ret = -EINVAL;
        }
 
+       IWL_DEBUG_WEP("Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n",
+                     keyconf->alg, keyconf->keylen, keyconf->keyidx,
+                     sta_id, ret);
+
        return ret;
 }
 EXPORT_SYMBOL(iwl_set_dynamic_key);
@@ -766,10 +823,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
        if (lq->sta_id == 0xFF)
                lq->sta_id = IWL_AP_ID;
 
-       iwl_dump_lq_cmd(priv,lq);
+       iwl_dump_lq_cmd(priv, lq);
 
-       if (iwl_is_associated(priv) && priv->assoc_station_added &&
-           priv->lq_mngr.lq_ready)
+       if (iwl_is_associated(priv) && priv->assoc_station_added)
                return  iwl_send_cmd(priv, &cmd);
 
        return 0;
@@ -783,7 +839,7 @@ EXPORT_SYMBOL(iwl_send_lq_cmd);
  * for automatic fallback during transmission.
  *
  * NOTE: This sets up a default set of values.  These will be replaced later
- *       if the driver's iwl-4965-rs rate scaling algorithm is used, instead of
+ *       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
@@ -816,7 +872,7 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap)
                rate_flags |= RATE_MCS_ANT_B_MSK; /*FIXME:RS*/
 
                link_cmd.rs_table[i].rate_n_flags =
-                       iwl4965_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
+                       iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
                r = iwl4965_get_prev_ieee_rate(r);
        }
 
@@ -831,6 +887,7 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap)
        iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD,
                               sizeof(link_cmd), &link_cmd, NULL);
 }
+
 /**
  * iwl_rxon_add_station - add station into station table.
  *
@@ -842,7 +899,6 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
        u8 sta_id;
 
        /* Add station to device's station table */
-#ifdef CONFIG_IWL4965_HT
        struct ieee80211_conf *conf = &priv->hw->conf;
        struct ieee80211_ht_info *cur_ht_config = &conf->ht_conf;
 
@@ -852,7 +908,6 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
                sta_id = iwl_add_station_flags(priv, addr, is_ap,
                                                   0, cur_ht_config);
        else
-#endif /* CONFIG_IWL4965_HT */
                sta_id = iwl_add_station_flags(priv, addr, is_ap,
                                                   0, NULL);
 
@@ -863,7 +918,6 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
 }
 EXPORT_SYMBOL(iwl_rxon_add_station);
 
-
 /**
  * iwl_get_sta_id - Find station's index within station table
  *
@@ -915,13 +969,12 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
                return priv->hw_params.bcast_sta_id;
 
        default:
-               IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode);
+               IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode);
                return priv->hw_params.bcast_sta_id;
        }
 }
 EXPORT_SYMBOL(iwl_get_sta_id);
 
-
 /**
  * iwl_sta_modify_enable_tid_tx - Enable Tx for this TID in station table
  */
@@ -940,4 +993,3 @@ void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid)
 }
 EXPORT_SYMBOL(iwl_sta_modify_enable_tid_tx);
 
-