diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl4965-base.c')
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 90 |
1 files changed, 51 insertions, 39 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index ecc9cba62bf9..dfd2b75492e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
| @@ -50,6 +50,7 @@ | |||
| 50 | #include "iwl-core.h" | 50 | #include "iwl-core.h" |
| 51 | #include "iwl-io.h" | 51 | #include "iwl-io.h" |
| 52 | #include "iwl-helpers.h" | 52 | #include "iwl-helpers.h" |
| 53 | #include "iwl-sta.h" | ||
| 53 | 54 | ||
| 54 | static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, | 55 | static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, |
| 55 | struct iwl4965_tx_queue *txq); | 56 | struct iwl4965_tx_queue *txq); |
| @@ -941,6 +942,9 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) | |||
| 941 | return -EIO; | 942 | return -EIO; |
| 942 | } | 943 | } |
| 943 | priv->assoc_station_added = 1; | 944 | priv->assoc_station_added = 1; |
| 945 | if (priv->default_wep_key && | ||
| 946 | iwl_send_static_wepkey_cmd(priv, 0)) | ||
| 947 | IWL_ERROR("Could not send WEP static key.\n"); | ||
| 944 | } | 948 | } |
| 945 | 949 | ||
| 946 | return 0; | 950 | return 0; |
| @@ -1180,6 +1184,8 @@ static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) | |||
| 1180 | { | 1184 | { |
| 1181 | unsigned long flags; | 1185 | unsigned long flags; |
| 1182 | 1186 | ||
| 1187 | priv->key_mapping_key = 0; | ||
| 1188 | |||
| 1183 | spin_lock_irqsave(&priv->sta_lock, flags); | 1189 | spin_lock_irqsave(&priv->sta_lock, flags); |
| 1184 | memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key)); | 1190 | memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key)); |
| 1185 | memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo)); | 1191 | memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo)); |
| @@ -1198,6 +1204,8 @@ static int iwl4965_set_dynamic_key(struct iwl_priv *priv, | |||
| 1198 | { | 1204 | { |
| 1199 | int ret; | 1205 | int ret; |
| 1200 | 1206 | ||
| 1207 | priv->key_mapping_key = 1; | ||
| 1208 | |||
| 1201 | switch (key->alg) { | 1209 | switch (key->alg) { |
| 1202 | case ALG_CCMP: | 1210 | case ALG_CCMP: |
| 1203 | ret = iwl4965_set_ccmp_dynamic_key_info(priv, key, sta_id); | 1211 | ret = iwl4965_set_ccmp_dynamic_key_info(priv, key, sta_id); |
| @@ -1216,23 +1224,6 @@ static int iwl4965_set_dynamic_key(struct iwl_priv *priv, | |||
| 1216 | return ret; | 1224 | return ret; |
| 1217 | } | 1225 | } |
| 1218 | 1226 | ||
| 1219 | static int iwl4965_remove_static_key(struct iwl_priv *priv) | ||
| 1220 | { | ||
| 1221 | int ret = -EOPNOTSUPP; | ||
| 1222 | |||
| 1223 | return ret; | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | static int iwl4965_set_static_key(struct iwl_priv *priv, | ||
| 1227 | struct ieee80211_key_conf *key) | ||
| 1228 | { | ||
| 1229 | if (key->alg == ALG_WEP) | ||
| 1230 | return -EOPNOTSUPP; | ||
| 1231 | |||
| 1232 | IWL_ERROR("Static key invalid: alg %d\n", key->alg); | ||
| 1233 | return -EINVAL; | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | static void iwl4965_clear_free_frames(struct iwl_priv *priv) | 1227 | static void iwl4965_clear_free_frames(struct iwl_priv *priv) |
| 1237 | { | 1228 | { |
| 1238 | struct list_head *element; | 1229 | struct list_head *element; |
| @@ -2115,6 +2106,10 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
| 2115 | int sta_id) | 2106 | int sta_id) |
| 2116 | { | 2107 | { |
| 2117 | struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; | 2108 | struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; |
| 2109 | struct iwl_wep_key *wepkey; | ||
| 2110 | int keyidx = 0; | ||
| 2111 | |||
| 2112 | BUG_ON(ctl->key_idx > 3); | ||
| 2118 | 2113 | ||
| 2119 | switch (keyinfo->alg) { | 2114 | switch (keyinfo->alg) { |
| 2120 | case ALG_CCMP: | 2115 | case ALG_CCMP: |
| @@ -2133,16 +2128,24 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
| 2133 | break; | 2128 | break; |
| 2134 | 2129 | ||
| 2135 | case ALG_WEP: | 2130 | case ALG_WEP: |
| 2136 | cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP | | 2131 | wepkey = &priv->wep_keys[ctl->key_idx]; |
| 2137 | (ctl->key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; | 2132 | cmd->cmd.tx.sec_ctl = 0; |
| 2138 | 2133 | if (priv->default_wep_key) { | |
| 2139 | if (keyinfo->keylen == 13) | 2134 | /* the WEP key was sent as static */ |
| 2140 | cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; | 2135 | keyidx = ctl->key_idx; |
| 2136 | memcpy(&cmd->cmd.tx.key[3], wepkey->key, | ||
| 2137 | wepkey->key_size); | ||
| 2138 | if (wepkey->key_size == WEP_KEY_LEN_128) | ||
| 2139 | cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; | ||
| 2140 | } else { | ||
| 2141 | IWL_ERROR("No support for WEP key mappings key\n"); | ||
| 2142 | } | ||
| 2141 | 2143 | ||
| 2142 | memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen); | 2144 | cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP | |
| 2145 | (keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); | ||
| 2143 | 2146 | ||
| 2144 | IWL_DEBUG_TX("Configuring packet for WEP encryption " | 2147 | IWL_DEBUG_TX("Configuring packet for WEP encryption " |
| 2145 | "with key %d\n", ctl->key_idx); | 2148 | "with key %d\n", keyidx); |
| 2146 | break; | 2149 | break; |
| 2147 | 2150 | ||
| 2148 | default: | 2151 | default: |
| @@ -6989,7 +6992,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
| 6989 | DECLARE_MAC_BUF(mac); | 6992 | DECLARE_MAC_BUF(mac); |
| 6990 | int ret = 0; | 6993 | int ret = 0; |
| 6991 | u8 sta_id = IWL_INVALID_STATION; | 6994 | u8 sta_id = IWL_INVALID_STATION; |
| 6992 | u8 static_key; | 6995 | u8 is_default_wep_key = 0; |
| 6993 | 6996 | ||
| 6994 | IWL_DEBUG_MAC80211("enter\n"); | 6997 | IWL_DEBUG_MAC80211("enter\n"); |
| 6995 | 6998 | ||
| @@ -7002,33 +7005,42 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
| 7002 | /* only support pairwise keys */ | 7005 | /* only support pairwise keys */ |
| 7003 | return -EOPNOTSUPP; | 7006 | return -EOPNOTSUPP; |
| 7004 | 7007 | ||
| 7005 | /* FIXME: need to differenciate between static and dynamic key | 7008 | sta_id = iwl4965_hw_find_station(priv, addr); |
| 7006 | * in the level of mac80211 */ | 7009 | if (sta_id == IWL_INVALID_STATION) { |
| 7007 | static_key = !iwl_is_associated(priv); | 7010 | IWL_DEBUG_MAC80211("leave - %s not in station map.\n", |
| 7011 | print_mac(mac, addr)); | ||
| 7012 | return -EINVAL; | ||
| 7008 | 7013 | ||
| 7009 | if (!static_key) { | ||
| 7010 | sta_id = iwl4965_hw_find_station(priv, addr); | ||
| 7011 | if (sta_id == IWL_INVALID_STATION) { | ||
| 7012 | IWL_DEBUG_MAC80211("leave - %s not in station map.\n", | ||
| 7013 | print_mac(mac, addr)); | ||
| 7014 | return -EINVAL; | ||
| 7015 | } | ||
| 7016 | } | 7014 | } |
| 7017 | 7015 | ||
| 7016 | mutex_lock(&priv->mutex); | ||
| 7018 | iwl4965_scan_cancel_timeout(priv, 100); | 7017 | iwl4965_scan_cancel_timeout(priv, 100); |
| 7018 | mutex_unlock(&priv->mutex); | ||
| 7019 | |||
| 7020 | /* If we are getting WEP group key and we didn't receive any key mapping | ||
| 7021 | * so far, we are in legacy wep mode (group key only), otherwise we are | ||
| 7022 | * in 1X mode. | ||
| 7023 | * In legacy wep mode, we use another host command to the uCode */ | ||
| 7024 | if (key->alg == ALG_WEP && sta_id == priv->hw_setting.bcast_sta_id && | ||
| 7025 | priv->iw_mode != IEEE80211_IF_TYPE_AP) { | ||
| 7026 | if (cmd == SET_KEY) | ||
| 7027 | is_default_wep_key = !priv->key_mapping_key; | ||
| 7028 | else | ||
| 7029 | is_default_wep_key = priv->default_wep_key; | ||
| 7030 | } | ||
| 7019 | 7031 | ||
| 7020 | switch (cmd) { | 7032 | switch (cmd) { |
| 7021 | case SET_KEY: | 7033 | case SET_KEY: |
| 7022 | if (static_key) | 7034 | if (is_default_wep_key) |
| 7023 | ret = iwl4965_set_static_key(priv, key); | 7035 | ret = iwl_set_default_wep_key(priv, key); |
| 7024 | else | 7036 | else |
| 7025 | ret = iwl4965_set_dynamic_key(priv, key, sta_id); | 7037 | ret = iwl4965_set_dynamic_key(priv, key, sta_id); |
| 7026 | 7038 | ||
| 7027 | IWL_DEBUG_MAC80211("enable hwcrypto key\n"); | 7039 | IWL_DEBUG_MAC80211("enable hwcrypto key\n"); |
| 7028 | break; | 7040 | break; |
| 7029 | case DISABLE_KEY: | 7041 | case DISABLE_KEY: |
| 7030 | if (static_key) | 7042 | if (is_default_wep_key) |
| 7031 | ret = iwl4965_remove_static_key(priv); | 7043 | ret = iwl_remove_default_wep_key(priv, key); |
| 7032 | else | 7044 | else |
| 7033 | ret = iwl4965_clear_sta_key_info(priv, sta_id); | 7045 | ret = iwl4965_clear_sta_key_info(priv, sta_id); |
| 7034 | 7046 | ||
