aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c53
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c53
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c41
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 */
2877static 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
2874static u32 iwl4965_translate_rx_status(u32 decrypt_in) 2921static 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);
674extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, 674extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv,
675 struct iwl4965_rx_queue *q); 675 struct iwl4965_rx_queue *q);
676extern void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
677 u32 decrypt_res,
678 struct ieee80211_rx_status *stats);
679extern __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr); 676extern __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr);
680int iwl4965_init_geos(struct iwl_priv *priv); 677int iwl4965_init_geos(struct iwl_priv *priv);
681void iwl4965_free_geos(struct iwl_priv *priv); 678void 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
294int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id) 308int 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
318int iwl_set_dynamic_key(struct iwl_priv *priv, 353int 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);
44int iwl_set_default_wep_key(struct iwl_priv *priv, 44int iwl_set_default_wep_key(struct iwl_priv *priv,
45 struct ieee80211_key_conf *key); 45 struct ieee80211_key_conf *key);
46int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id);
47int iwl_set_dynamic_key(struct iwl_priv *priv, 46int 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);
48int 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
2459void 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
2500int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header) 2461int 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;