diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 66 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 6 |
3 files changed, 81 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 085d8137bfb8..1d82f105cc26 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h | |||
@@ -890,6 +890,10 @@ struct iwl4965_rx_frame_hdr { | |||
890 | #define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8) | 890 | #define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8) |
891 | #define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8) | 891 | #define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8) |
892 | #define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8) | 892 | #define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8) |
893 | #define RX_RES_STATUS_SEC_TYPE_ERR (0x7 << 8) | ||
894 | |||
895 | #define RX_RES_STATUS_STATION_FOUND (1<<6) | ||
896 | #define RX_RES_STATUS_NO_STATION_INFO_MISMATCH (1<<7) | ||
893 | 897 | ||
894 | #define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11) | 898 | #define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11) |
895 | #define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11) | 899 | #define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11) |
@@ -897,6 +901,11 @@ struct iwl4965_rx_frame_hdr { | |||
897 | #define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11) | 901 | #define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11) |
898 | #define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11) | 902 | #define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11) |
899 | 903 | ||
904 | #define RX_MPDU_RES_STATUS_ICV_OK (0x20) | ||
905 | #define RX_MPDU_RES_STATUS_MIC_OK (0x40) | ||
906 | #define RX_MPDU_RES_STATUS_TTAK_OK (1 << 7) | ||
907 | #define RX_MPDU_RES_STATUS_DEC_DONE_MSK (0x800) | ||
908 | |||
900 | struct iwl4965_rx_frame_end { | 909 | struct iwl4965_rx_frame_end { |
901 | __le32 status; | 910 | __le32 status; |
902 | __le64 timestamp; | 911 | __le64 timestamp; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 8b2d04ed43d6..03c032e9b581 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -3393,6 +3393,65 @@ static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len) | |||
3393 | priv->rx_stats[idx].bytes += len; | 3393 | priv->rx_stats[idx].bytes += len; |
3394 | } | 3394 | } |
3395 | 3395 | ||
3396 | static u32 iwl4965_translate_rx_status(u32 decrypt_in) | ||
3397 | { | ||
3398 | u32 decrypt_out = 0; | ||
3399 | |||
3400 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
3401 | RX_RES_STATUS_STATION_FOUND) | ||
3402 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
3403 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
3404 | |||
3405 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
3406 | |||
3407 | /* packet was not encrypted */ | ||
3408 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
3409 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
3410 | return decrypt_out; | ||
3411 | |||
3412 | /* packet was encrypted with unknown alg */ | ||
3413 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
3414 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
3415 | return decrypt_out; | ||
3416 | |||
3417 | /* decryption was not done in HW */ | ||
3418 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
3419 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
3420 | return decrypt_out; | ||
3421 | |||
3422 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
3423 | |||
3424 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
3425 | /* alg is CCM: check MIC only */ | ||
3426 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
3427 | /* Bad MIC */ | ||
3428 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
3429 | else | ||
3430 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
3431 | |||
3432 | break; | ||
3433 | |||
3434 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
3435 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
3436 | /* Bad TTAK */ | ||
3437 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
3438 | break; | ||
3439 | } | ||
3440 | /* fall through if TTAK OK */ | ||
3441 | default: | ||
3442 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
3443 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
3444 | else | ||
3445 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
3446 | break; | ||
3447 | }; | ||
3448 | |||
3449 | IWL_DEBUG_RX("decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
3450 | decrypt_in, decrypt_out); | ||
3451 | |||
3452 | return decrypt_out; | ||
3453 | } | ||
3454 | |||
3396 | static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, | 3455 | static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, |
3397 | int include_phy, | 3456 | int include_phy, |
3398 | struct iwl4965_rx_mem_buffer *rxb, | 3457 | struct iwl4965_rx_mem_buffer *rxb, |
@@ -3406,6 +3465,7 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, | |||
3406 | __le32 *rx_end; | 3465 | __le32 *rx_end; |
3407 | unsigned int skblen; | 3466 | unsigned int skblen; |
3408 | u32 ampdu_status; | 3467 | u32 ampdu_status; |
3468 | u32 ampdu_status_legacy; | ||
3409 | 3469 | ||
3410 | if (!include_phy && priv->last_phy_res[0]) | 3470 | if (!include_phy && priv->last_phy_res[0]) |
3411 | rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; | 3471 | rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; |
@@ -3442,6 +3502,12 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, | |||
3442 | ampdu_status = le32_to_cpu(*rx_end); | 3502 | ampdu_status = le32_to_cpu(*rx_end); |
3443 | skblen = ((u8 *) rx_end - (u8 *) & pkt->u.raw[0]) + sizeof(u32); | 3503 | skblen = ((u8 *) rx_end - (u8 *) & pkt->u.raw[0]) + sizeof(u32); |
3444 | 3504 | ||
3505 | if (!include_phy) { | ||
3506 | /* New status scheme, need to translate */ | ||
3507 | ampdu_status_legacy = ampdu_status; | ||
3508 | ampdu_status = iwl4965_translate_rx_status(ampdu_status); | ||
3509 | } | ||
3510 | |||
3445 | /* start from MAC */ | 3511 | /* start from MAC */ |
3446 | skb_reserve(rxb->skb, (void *)hdr - (void *)pkt); | 3512 | skb_reserve(rxb->skb, (void *)hdr - (void *)pkt); |
3447 | skb_put(rxb->skb, len); /* end where data ends */ | 3513 | skb_put(rxb->skb, len); /* end where data ends */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index fc3e23a2d8eb..8de301d1da8e 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -2856,6 +2856,12 @@ void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, | |||
2856 | IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res); | 2856 | IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res); |
2857 | switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) { | 2857 | switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) { |
2858 | case RX_RES_STATUS_SEC_TYPE_TKIP: | 2858 | case RX_RES_STATUS_SEC_TYPE_TKIP: |
2859 | /* The uCode has got a bad phase 1 Key, pushes the packet. | ||
2860 | * Decryption will be done in SW. */ | ||
2861 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2862 | RX_RES_STATUS_BAD_KEY_TTAK) | ||
2863 | break; | ||
2864 | |||
2859 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | 2865 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == |
2860 | RX_RES_STATUS_BAD_ICV_MIC) | 2866 | RX_RES_STATUS_BAD_ICV_MIC) |
2861 | stats->flag |= RX_FLAG_MMIC_ERROR; | 2867 | stats->flag |= RX_FLAG_MMIC_ERROR; |