aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-4965.c
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/net/wireless/iwlwifi/iwl-4965.c
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/net/wireless/iwlwifi/iwl-4965.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c66
1 files changed, 66 insertions, 0 deletions
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 */