diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2008-03-19 19:41:42 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-03-25 16:41:52 -0400 |
commit | 17e476b8db13790c03e2c46d93abc71468fca47e (patch) | |
tree | 8981190d5696cb984939a1fbca8dab4120aa33c4 /drivers/net/wireless/iwlwifi/iwl-4965.c | |
parent | deb09c435e3f947f8b2c9d5df6a9c0a5b472b125 (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.c | 66 |
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 | ||
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 */ |