diff options
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 */ |