aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2008-03-19 19:41:42 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-03-25 16:41:52 -0400
commit17e476b8db13790c03e2c46d93abc71468fca47e (patch)
tree8981190d5696cb984939a1fbca8dab4120aa33c4 /drivers
parentdeb09c435e3f947f8b2c9d5df6a9c0a5b472b125 (diff)
iwlwifi-2.6: RX status translation to old scheme
This patch adds translation for the RX status of an incoming packet. The incoming status has to be translated to the old scheme in order to know if the decryption has been done, MIC failure has occured, TTAK is valid etc... This translation is mandatory for all RX packets when using 5300 and for all HT packets using 4965. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
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;