diff options
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 165 |
2 files changed, 110 insertions, 56 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 1025ffeb8fa8..085d8137bfb8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h | |||
@@ -741,6 +741,7 @@ struct iwl4965_qosparam_cmd { | |||
741 | /* wep key in STA: 5-bytes (0) or 13-bytes (1) */ | 741 | /* wep key in STA: 5-bytes (0) or 13-bytes (1) */ |
742 | #define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000) | 742 | #define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000) |
743 | #define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000) | 743 | #define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000) |
744 | #define STA_KEY_MAX_NUM 8 | ||
744 | 745 | ||
745 | /* Flags indicate whether to modify vs. don't change various station params */ | 746 | /* Flags indicate whether to modify vs. don't change various station params */ |
746 | #define STA_MODIFY_KEY_MASK 0x01 | 747 | #define STA_MODIFY_KEY_MASK 0x01 |
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 9cf1f204666d..fc3e23a2d8eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -796,6 +796,17 @@ out: | |||
796 | return ret; | 796 | return ret; |
797 | } | 797 | } |
798 | 798 | ||
799 | static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) | ||
800 | { | ||
801 | struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon; | ||
802 | |||
803 | if (hw_decrypt) | ||
804 | rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; | ||
805 | else | ||
806 | rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK; | ||
807 | |||
808 | } | ||
809 | |||
799 | int iwl4965_send_cmd(struct iwl_priv *priv, struct iwl4965_host_cmd *cmd) | 810 | int iwl4965_send_cmd(struct iwl_priv *priv, struct iwl4965_host_cmd *cmd) |
800 | { | 811 | { |
801 | if (cmd->meta.flags & CMD_ASYNC) | 812 | if (cmd->meta.flags & CMD_ASYNC) |
@@ -1124,6 +1135,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) | |||
1124 | le16_to_cpu(priv->staging_rxon.channel), | 1135 | le16_to_cpu(priv->staging_rxon.channel), |
1125 | print_mac(mac, priv->staging_rxon.bssid_addr)); | 1136 | print_mac(mac, priv->staging_rxon.bssid_addr)); |
1126 | 1137 | ||
1138 | iwl4965_set_rxon_hwcrypto(priv, priv->cfg->mod_params->hw_crypto); | ||
1127 | /* Apply the new configuration */ | 1139 | /* Apply the new configuration */ |
1128 | rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON, | 1140 | rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON, |
1129 | sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon); | 1141 | sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon); |
@@ -1336,33 +1348,36 @@ int iwl4965_send_add_station(struct iwl_priv *priv, | |||
1336 | return rc; | 1348 | return rc; |
1337 | } | 1349 | } |
1338 | 1350 | ||
1339 | static int iwl4965_update_sta_key_info(struct iwl_priv *priv, | 1351 | static int iwl4965_set_ccmp_dynamic_key_info(struct iwl_priv *priv, |
1340 | struct ieee80211_key_conf *keyconf, | 1352 | struct ieee80211_key_conf *keyconf, |
1341 | u8 sta_id) | 1353 | u8 sta_id) |
1342 | { | 1354 | { |
1343 | unsigned long flags; | 1355 | unsigned long flags; |
1344 | __le16 key_flags = 0; | 1356 | __le16 key_flags = 0; |
1345 | 1357 | ||
1346 | switch (keyconf->alg) { | 1358 | key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); |
1347 | case ALG_CCMP: | 1359 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); |
1348 | key_flags |= STA_KEY_FLG_CCMP; | 1360 | |
1349 | key_flags |= cpu_to_le16( | 1361 | if (sta_id == priv->hw_setting.bcast_sta_id) |
1350 | keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | 1362 | key_flags |= STA_KEY_MULTICAST_MSK; |
1351 | key_flags &= ~STA_KEY_FLG_INVALID; | 1363 | |
1352 | break; | 1364 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1353 | case ALG_TKIP: | 1365 | keyconf->hw_key_idx = keyconf->keyidx; |
1354 | case ALG_WEP: | 1366 | |
1355 | default: | 1367 | key_flags &= ~STA_KEY_FLG_INVALID; |
1356 | return -EINVAL; | 1368 | |
1357 | } | ||
1358 | spin_lock_irqsave(&priv->sta_lock, flags); | 1369 | spin_lock_irqsave(&priv->sta_lock, flags); |
1359 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | 1370 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; |
1360 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; | 1371 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; |
1372 | |||
1361 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, | 1373 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, |
1362 | keyconf->keylen); | 1374 | keyconf->keylen); |
1363 | 1375 | ||
1364 | memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, | 1376 | memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, |
1365 | keyconf->keylen); | 1377 | keyconf->keylen); |
1378 | |||
1379 | priv->stations[sta_id].sta.key.key_offset | ||
1380 | = (sta_id % STA_KEY_MAX_NUM);/*FIXME*/ | ||
1366 | priv->stations[sta_id].sta.key.key_flags = key_flags; | 1381 | priv->stations[sta_id].sta.key.key_flags = key_flags; |
1367 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | 1382 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; |
1368 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1383 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
@@ -1370,8 +1385,15 @@ static int iwl4965_update_sta_key_info(struct iwl_priv *priv, | |||
1370 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1385 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1371 | 1386 | ||
1372 | IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n"); | 1387 | IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n"); |
1373 | iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0); | 1388 | return iwl4965_send_add_station(priv, |
1374 | return 0; | 1389 | &priv->stations[sta_id].sta, CMD_ASYNC); |
1390 | } | ||
1391 | |||
1392 | static int iwl4965_set_tkip_dynamic_key_info(struct iwl_priv *priv, | ||
1393 | struct ieee80211_key_conf *keyconf, | ||
1394 | u8 sta_id) | ||
1395 | { | ||
1396 | return -EOPNOTSUPP; | ||
1375 | } | 1397 | } |
1376 | 1398 | ||
1377 | static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) | 1399 | static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) |
@@ -1391,6 +1413,46 @@ static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) | |||
1391 | return 0; | 1413 | return 0; |
1392 | } | 1414 | } |
1393 | 1415 | ||
1416 | static int iwl4965_set_dynamic_key(struct iwl_priv *priv, | ||
1417 | struct ieee80211_key_conf *key, u8 sta_id) | ||
1418 | { | ||
1419 | int ret; | ||
1420 | |||
1421 | switch (key->alg) { | ||
1422 | case ALG_CCMP: | ||
1423 | ret = iwl4965_set_ccmp_dynamic_key_info(priv, key, sta_id); | ||
1424 | break; | ||
1425 | case ALG_TKIP: | ||
1426 | ret = iwl4965_set_tkip_dynamic_key_info(priv, key, sta_id); | ||
1427 | break; | ||
1428 | case ALG_WEP: | ||
1429 | ret = -EOPNOTSUPP; | ||
1430 | break; | ||
1431 | default: | ||
1432 | IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg); | ||
1433 | ret = -EINVAL; | ||
1434 | } | ||
1435 | |||
1436 | return ret; | ||
1437 | } | ||
1438 | |||
1439 | static int iwl4965_remove_static_key(struct iwl_priv *priv) | ||
1440 | { | ||
1441 | int ret = -EOPNOTSUPP; | ||
1442 | |||
1443 | return ret; | ||
1444 | } | ||
1445 | |||
1446 | static int iwl4965_set_static_key(struct iwl_priv *priv, | ||
1447 | struct ieee80211_key_conf *key) | ||
1448 | { | ||
1449 | if (key->alg == ALG_WEP) | ||
1450 | return -EOPNOTSUPP; | ||
1451 | |||
1452 | IWL_ERROR("Static key invalid: alg %d\n", key->alg); | ||
1453 | return -EINVAL; | ||
1454 | } | ||
1455 | |||
1394 | static void iwl4965_clear_free_frames(struct iwl_priv *priv) | 1456 | static void iwl4965_clear_free_frames(struct iwl_priv *priv) |
1395 | { | 1457 | { |
1396 | struct list_head *element; | 1458 | struct list_head *element; |
@@ -2122,17 +2184,6 @@ static int iwl4965_scan_initiate(struct iwl_priv *priv) | |||
2122 | return 0; | 2184 | return 0; |
2123 | } | 2185 | } |
2124 | 2186 | ||
2125 | static int iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) | ||
2126 | { | ||
2127 | struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon; | ||
2128 | |||
2129 | if (hw_decrypt) | ||
2130 | rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; | ||
2131 | else | ||
2132 | rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK; | ||
2133 | |||
2134 | return 0; | ||
2135 | } | ||
2136 | 2187 | ||
2137 | static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv, | 2188 | static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv, |
2138 | enum ieee80211_band band) | 2189 | enum ieee80211_band band) |
@@ -2276,9 +2327,9 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
2276 | struct ieee80211_tx_control *ctl, | 2327 | struct ieee80211_tx_control *ctl, |
2277 | struct iwl4965_cmd *cmd, | 2328 | struct iwl4965_cmd *cmd, |
2278 | struct sk_buff *skb_frag, | 2329 | struct sk_buff *skb_frag, |
2279 | int last_frag) | 2330 | int sta_id) |
2280 | { | 2331 | { |
2281 | struct iwl4965_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo; | 2332 | struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; |
2282 | 2333 | ||
2283 | switch (keyinfo->alg) { | 2334 | switch (keyinfo->alg) { |
2284 | case ALG_CCMP: | 2335 | case ALG_CCMP: |
@@ -2614,7 +2665,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, | |||
2614 | iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); | 2665 | iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); |
2615 | 2666 | ||
2616 | if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) | 2667 | if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) |
2617 | iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0); | 2668 | iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, sta_id); |
2618 | 2669 | ||
2619 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | 2670 | /* Set up TFD's 2nd entry to point directly to remainder of skb, |
2620 | * if any (802.11 null frames have no payload). */ | 2671 | * if any (802.11 null frames have no payload). */ |
@@ -7121,8 +7172,9 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
7121 | { | 7172 | { |
7122 | struct iwl_priv *priv = hw->priv; | 7173 | struct iwl_priv *priv = hw->priv; |
7123 | DECLARE_MAC_BUF(mac); | 7174 | DECLARE_MAC_BUF(mac); |
7124 | int rc = 0; | 7175 | int ret = 0; |
7125 | u8 sta_id; | 7176 | u8 sta_id = IWL_INVALID_STATION; |
7177 | u8 static_key; | ||
7126 | 7178 | ||
7127 | IWL_DEBUG_MAC80211("enter\n"); | 7179 | IWL_DEBUG_MAC80211("enter\n"); |
7128 | 7180 | ||
@@ -7135,44 +7187,45 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
7135 | /* only support pairwise keys */ | 7187 | /* only support pairwise keys */ |
7136 | return -EOPNOTSUPP; | 7188 | return -EOPNOTSUPP; |
7137 | 7189 | ||
7138 | sta_id = iwl4965_hw_find_station(priv, addr); | 7190 | /* FIXME: need to differenciate between static and dynamic key |
7139 | if (sta_id == IWL_INVALID_STATION) { | 7191 | * in the level of mac80211 */ |
7140 | IWL_DEBUG_MAC80211("leave - %s not in station map.\n", | 7192 | static_key = !iwl4965_is_associated(priv); |
7141 | print_mac(mac, addr)); | ||
7142 | return -EINVAL; | ||
7143 | } | ||
7144 | 7193 | ||
7145 | mutex_lock(&priv->mutex); | 7194 | if (!static_key) { |
7195 | sta_id = iwl4965_hw_find_station(priv, addr); | ||
7196 | if (sta_id == IWL_INVALID_STATION) { | ||
7197 | IWL_DEBUG_MAC80211("leave - %s not in station map.\n", | ||
7198 | print_mac(mac, addr)); | ||
7199 | return -EINVAL; | ||
7200 | } | ||
7201 | } | ||
7146 | 7202 | ||
7147 | iwl4965_scan_cancel_timeout(priv, 100); | 7203 | iwl4965_scan_cancel_timeout(priv, 100); |
7148 | 7204 | ||
7149 | switch (cmd) { | 7205 | switch (cmd) { |
7150 | case SET_KEY: | 7206 | case SET_KEY: |
7151 | rc = iwl4965_update_sta_key_info(priv, key, sta_id); | 7207 | if (static_key) |
7152 | if (!rc) { | 7208 | ret = iwl4965_set_static_key(priv, key); |
7153 | iwl4965_set_rxon_hwcrypto(priv, 1); | 7209 | else |
7154 | iwl4965_commit_rxon(priv); | 7210 | ret = iwl4965_set_dynamic_key(priv, key, sta_id); |
7155 | key->hw_key_idx = sta_id; | 7211 | |
7156 | IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n"); | 7212 | IWL_DEBUG_MAC80211("enable hwcrypto key\n"); |
7157 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
7158 | } | ||
7159 | break; | 7213 | break; |
7160 | case DISABLE_KEY: | 7214 | case DISABLE_KEY: |
7161 | rc = iwl4965_clear_sta_key_info(priv, sta_id); | 7215 | if (static_key) |
7162 | if (!rc) { | 7216 | ret = iwl4965_remove_static_key(priv); |
7163 | iwl4965_set_rxon_hwcrypto(priv, 0); | 7217 | else |
7164 | iwl4965_commit_rxon(priv); | 7218 | ret = iwl4965_clear_sta_key_info(priv, sta_id); |
7165 | IWL_DEBUG_MAC80211("disable hwcrypto key\n"); | 7219 | |
7166 | } | 7220 | IWL_DEBUG_MAC80211("disable hwcrypto key\n"); |
7167 | break; | 7221 | break; |
7168 | default: | 7222 | default: |
7169 | rc = -EINVAL; | 7223 | ret = -EINVAL; |
7170 | } | 7224 | } |
7171 | 7225 | ||
7172 | IWL_DEBUG_MAC80211("leave\n"); | 7226 | IWL_DEBUG_MAC80211("leave\n"); |
7173 | mutex_unlock(&priv->mutex); | ||
7174 | 7227 | ||
7175 | return rc; | 7228 | return ret; |
7176 | } | 7229 | } |
7177 | 7230 | ||
7178 | static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue, | 7231 | static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue, |