diff options
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 53 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sta.c | 53 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sta.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 41 |
5 files changed, 98 insertions, 55 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 69a355bbb97a..ddcd1b232549 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -2871,6 +2871,53 @@ static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len) | |||
2871 | priv->rx_stats[idx].bytes += len; | 2871 | priv->rx_stats[idx].bytes += len; |
2872 | } | 2872 | } |
2873 | 2873 | ||
2874 | /* | ||
2875 | * returns non-zero if packet should be dropped | ||
2876 | */ | ||
2877 | static int iwl4965_set_decrypted_flag(struct iwl_priv *priv, | ||
2878 | struct ieee80211_hdr *hdr, | ||
2879 | u32 decrypt_res, | ||
2880 | struct ieee80211_rx_status *stats) | ||
2881 | { | ||
2882 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
2883 | |||
2884 | if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) | ||
2885 | return 0; | ||
2886 | |||
2887 | if (!(fc & IEEE80211_FCTL_PROTECTED)) | ||
2888 | return 0; | ||
2889 | |||
2890 | IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res); | ||
2891 | switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
2892 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
2893 | /* The uCode has got a bad phase 1 Key, pushes the packet. | ||
2894 | * Decryption will be done in SW. */ | ||
2895 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2896 | RX_RES_STATUS_BAD_KEY_TTAK) | ||
2897 | break; | ||
2898 | |||
2899 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2900 | RX_RES_STATUS_BAD_ICV_MIC) { | ||
2901 | /* bad ICV, the packet is destroyed since the | ||
2902 | * decryption is inplace, drop it */ | ||
2903 | IWL_DEBUG_RX("Packet destroyed\n"); | ||
2904 | return -1; | ||
2905 | } | ||
2906 | case RX_RES_STATUS_SEC_TYPE_WEP: | ||
2907 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
2908 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2909 | RX_RES_STATUS_DECRYPT_OK) { | ||
2910 | IWL_DEBUG_RX("hw decrypt successfully!!!\n"); | ||
2911 | stats->flag |= RX_FLAG_DECRYPTED; | ||
2912 | } | ||
2913 | break; | ||
2914 | |||
2915 | default: | ||
2916 | break; | ||
2917 | } | ||
2918 | return 0; | ||
2919 | } | ||
2920 | |||
2874 | static u32 iwl4965_translate_rx_status(u32 decrypt_in) | 2921 | static u32 iwl4965_translate_rx_status(u32 decrypt_in) |
2875 | { | 2922 | { |
2876 | u32 decrypt_out = 0; | 2923 | u32 decrypt_out = 0; |
@@ -3000,8 +3047,10 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, | |||
3000 | stats->flag = 0; | 3047 | stats->flag = 0; |
3001 | hdr = (struct ieee80211_hdr *)rxb->skb->data; | 3048 | hdr = (struct ieee80211_hdr *)rxb->skb->data; |
3002 | 3049 | ||
3003 | if (!priv->cfg->mod_params->sw_crypto) | 3050 | /* in case of HW accelerated crypto and bad decryption, drop */ |
3004 | iwl4965_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats); | 3051 | if (!priv->cfg->mod_params->sw_crypto && |
3052 | iwl4965_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
3053 | return; | ||
3005 | 3054 | ||
3006 | if (priv->add_radiotap) | 3055 | if (priv->add_radiotap) |
3007 | iwl4965_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status); | 3056 | iwl4965_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 2c26d020103e..ca2ce27ee7f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h | |||
@@ -673,9 +673,6 @@ extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, | |||
673 | const u8 *dest, int left); | 673 | const u8 *dest, int left); |
674 | extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, | 674 | extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, |
675 | struct iwl4965_rx_queue *q); | 675 | struct iwl4965_rx_queue *q); |
676 | extern void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, | ||
677 | u32 decrypt_res, | ||
678 | struct ieee80211_rx_status *stats); | ||
679 | extern __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr); | 676 | extern __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr); |
680 | int iwl4965_init_geos(struct iwl_priv *priv); | 677 | int iwl4965_init_geos(struct iwl_priv *priv); |
681 | void iwl4965_free_geos(struct iwl_priv *priv); | 678 | void iwl4965_free_geos(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index fa463ce6399b..d39ac1cffb57 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -207,10 +207,14 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, | |||
207 | memcpy(&priv->stations[sta_id].sta.key.key[3], | 207 | memcpy(&priv->stations[sta_id].sta.key.key[3], |
208 | keyconf->key, keyconf->keylen); | 208 | keyconf->key, keyconf->keylen); |
209 | 209 | ||
210 | priv->stations[sta_id].sta.key.key_offset = | 210 | if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) |
211 | == STA_KEY_FLG_NO_ENC) | ||
212 | priv->stations[sta_id].sta.key.key_offset = | ||
211 | iwl_get_free_ucode_key_index(priv); | 213 | iwl_get_free_ucode_key_index(priv); |
212 | priv->stations[sta_id].sta.key.key_flags = key_flags; | 214 | /* else, we are overriding an existing key => no need to allocated room |
215 | * in uCode. */ | ||
213 | 216 | ||
217 | priv->stations[sta_id].sta.key.key_flags = key_flags; | ||
214 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | 218 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; |
215 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 219 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
216 | 220 | ||
@@ -249,8 +253,13 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, | |||
249 | memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, | 253 | memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, |
250 | keyconf->keylen); | 254 | keyconf->keylen); |
251 | 255 | ||
252 | priv->stations[sta_id].sta.key.key_offset = | 256 | if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) |
253 | iwl_get_free_ucode_key_index(priv); | 257 | == STA_KEY_FLG_NO_ENC) |
258 | priv->stations[sta_id].sta.key.key_offset = | ||
259 | iwl_get_free_ucode_key_index(priv); | ||
260 | /* else, we are overriding an existing key => no need to allocated room | ||
261 | * in uCode. */ | ||
262 | |||
254 | priv->stations[sta_id].sta.key.key_flags = key_flags; | 263 | priv->stations[sta_id].sta.key.key_flags = key_flags; |
255 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | 264 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; |
256 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 265 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
@@ -278,8 +287,13 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, | |||
278 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | 287 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; |
279 | priv->stations[sta_id].keyinfo.conf = keyconf; | 288 | priv->stations[sta_id].keyinfo.conf = keyconf; |
280 | priv->stations[sta_id].keyinfo.keylen = 16; | 289 | priv->stations[sta_id].keyinfo.keylen = 16; |
281 | priv->stations[sta_id].sta.key.key_offset = | 290 | |
291 | if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) | ||
292 | == STA_KEY_FLG_NO_ENC) | ||
293 | priv->stations[sta_id].sta.key.key_offset = | ||
282 | iwl_get_free_ucode_key_index(priv); | 294 | iwl_get_free_ucode_key_index(priv); |
295 | /* else, we are overriding an existing key => no need to allocated room | ||
296 | * in uCode. */ | ||
283 | 297 | ||
284 | /* This copy is acutally not needed: we get the key with each TX */ | 298 | /* This copy is acutally not needed: we get the key with each TX */ |
285 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); | 299 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); |
@@ -291,13 +305,31 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, | |||
291 | return ret; | 305 | return ret; |
292 | } | 306 | } |
293 | 307 | ||
294 | int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id) | 308 | int iwl_remove_dynamic_key(struct iwl_priv *priv, |
309 | struct ieee80211_key_conf *keyconf, | ||
310 | u8 sta_id) | ||
295 | { | 311 | { |
296 | unsigned long flags; | 312 | unsigned long flags; |
313 | int ret = 0; | ||
314 | u16 key_flags; | ||
315 | u8 keyidx; | ||
297 | 316 | ||
298 | priv->key_mapping_key = 0; | 317 | priv->key_mapping_key = 0; |
299 | 318 | ||
300 | spin_lock_irqsave(&priv->sta_lock, flags); | 319 | spin_lock_irqsave(&priv->sta_lock, flags); |
320 | key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags); | ||
321 | keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3; | ||
322 | |||
323 | if (keyconf->keyidx != keyidx) { | ||
324 | /* We need to remove a key with index different that the one | ||
325 | * in the uCode. This means that the key we need to remove has | ||
326 | * been replaced by another one with different index. | ||
327 | * Don't do anything and return ok | ||
328 | */ | ||
329 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
330 | return 0; | ||
331 | } | ||
332 | |||
301 | if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset, | 333 | if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset, |
302 | &priv->ucode_key_table)) | 334 | &priv->ucode_key_table)) |
303 | IWL_ERROR("index %d not used in uCode key table.\n", | 335 | IWL_ERROR("index %d not used in uCode key table.\n", |
@@ -306,13 +338,16 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id) | |||
306 | sizeof(struct iwl4965_hw_key)); | 338 | sizeof(struct iwl4965_hw_key)); |
307 | memset(&priv->stations[sta_id].sta.key, 0, | 339 | memset(&priv->stations[sta_id].sta.key, 0, |
308 | sizeof(struct iwl4965_keyinfo)); | 340 | sizeof(struct iwl4965_keyinfo)); |
309 | priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; | 341 | priv->stations[sta_id].sta.key.key_flags = |
342 | STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID; | ||
343 | priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET; | ||
310 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | 344 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; |
311 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 345 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
312 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
313 | 346 | ||
314 | IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n"); | 347 | IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n"); |
315 | return iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0); | 348 | ret = iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0); |
349 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
350 | return ret; | ||
316 | } | 351 | } |
317 | 352 | ||
318 | int iwl_set_dynamic_key(struct iwl_priv *priv, | 353 | int iwl_set_dynamic_key(struct iwl_priv *priv, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 44f272ecc827..89558356a590 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h | |||
@@ -43,7 +43,8 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, | |||
43 | struct ieee80211_key_conf *key); | 43 | struct ieee80211_key_conf *key); |
44 | int iwl_set_default_wep_key(struct iwl_priv *priv, | 44 | int iwl_set_default_wep_key(struct iwl_priv *priv, |
45 | struct ieee80211_key_conf *key); | 45 | struct ieee80211_key_conf *key); |
46 | int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id); | ||
47 | int iwl_set_dynamic_key(struct iwl_priv *priv, | 46 | int iwl_set_dynamic_key(struct iwl_priv *priv, |
48 | struct ieee80211_key_conf *key, u8 sta_id); | 47 | struct ieee80211_key_conf *key, u8 sta_id); |
48 | int iwl_remove_dynamic_key(struct iwl_priv *priv, | ||
49 | struct ieee80211_key_conf *key, u8 sta_id); | ||
49 | #endif /* __iwl_sta_h__ */ | 50 | #endif /* __iwl_sta_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index e43ea5377d8e..50f12a6133e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -2456,45 +2456,6 @@ void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) | |||
2456 | return; | 2456 | return; |
2457 | } | 2457 | } |
2458 | 2458 | ||
2459 | void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, | ||
2460 | u32 decrypt_res, struct ieee80211_rx_status *stats) | ||
2461 | { | ||
2462 | u16 fc = | ||
2463 | le16_to_cpu(((struct ieee80211_hdr *)skb->data)->frame_control); | ||
2464 | |||
2465 | if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) | ||
2466 | return; | ||
2467 | |||
2468 | if (!(fc & IEEE80211_FCTL_PROTECTED)) | ||
2469 | return; | ||
2470 | |||
2471 | IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res); | ||
2472 | switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
2473 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
2474 | /* The uCode has got a bad phase 1 Key, pushes the packet. | ||
2475 | * Decryption will be done in SW. */ | ||
2476 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2477 | RX_RES_STATUS_BAD_KEY_TTAK) | ||
2478 | break; | ||
2479 | |||
2480 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2481 | RX_RES_STATUS_BAD_ICV_MIC) | ||
2482 | stats->flag |= RX_FLAG_MMIC_ERROR; | ||
2483 | case RX_RES_STATUS_SEC_TYPE_WEP: | ||
2484 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
2485 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2486 | RX_RES_STATUS_DECRYPT_OK) { | ||
2487 | IWL_DEBUG_RX("hw decrypt successfully!!!\n"); | ||
2488 | stats->flag |= RX_FLAG_DECRYPTED; | ||
2489 | } | ||
2490 | break; | ||
2491 | |||
2492 | default: | ||
2493 | break; | ||
2494 | } | ||
2495 | } | ||
2496 | |||
2497 | |||
2498 | #define IWL_PACKET_RETRY_TIME HZ | 2459 | #define IWL_PACKET_RETRY_TIME HZ |
2499 | 2460 | ||
2500 | int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header) | 2461 | int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header) |
@@ -6861,7 +6822,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
6861 | if (is_default_wep_key) | 6822 | if (is_default_wep_key) |
6862 | ret = iwl_remove_default_wep_key(priv, key); | 6823 | ret = iwl_remove_default_wep_key(priv, key); |
6863 | else | 6824 | else |
6864 | ret = iwl_remove_dynamic_key(priv, sta_id); | 6825 | ret = iwl_remove_dynamic_key(priv, key, sta_id); |
6865 | 6826 | ||
6866 | IWL_DEBUG_MAC80211("disable hwcrypto key\n"); | 6827 | IWL_DEBUG_MAC80211("disable hwcrypto key\n"); |
6867 | break; | 6828 | break; |