aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-commands.h9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c66
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c6
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
900struct iwl4965_rx_frame_end { 909struct 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
3396static 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
3396static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, 3455static 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;