diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-rx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rx.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index dc06c7bb0f5c..ea309f42a78a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -602,11 +602,15 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, | |||
602 | 602 | ||
603 | #define REG_RECALIB_PERIOD (60) | 603 | #define REG_RECALIB_PERIOD (60) |
604 | 604 | ||
605 | #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" | ||
605 | void iwl_rx_statistics(struct iwl_priv *priv, | 606 | void iwl_rx_statistics(struct iwl_priv *priv, |
606 | struct iwl_rx_mem_buffer *rxb) | 607 | struct iwl_rx_mem_buffer *rxb) |
607 | { | 608 | { |
608 | int change; | 609 | int change; |
609 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 610 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
611 | int combined_plcp_delta; | ||
612 | unsigned int plcp_msec; | ||
613 | unsigned long plcp_received_jiffies; | ||
610 | 614 | ||
611 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | 615 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", |
612 | (int)sizeof(priv->statistics), | 616 | (int)sizeof(priv->statistics), |
@@ -621,6 +625,56 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
621 | #ifdef CONFIG_IWLWIFI_DEBUG | 625 | #ifdef CONFIG_IWLWIFI_DEBUG |
622 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | 626 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); |
623 | #endif | 627 | #endif |
628 | /* | ||
629 | * check for plcp_err and trigger radio reset if it exceeds | ||
630 | * the plcp error threshold plcp_delta. | ||
631 | */ | ||
632 | plcp_received_jiffies = jiffies; | ||
633 | plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies - | ||
634 | (long) priv->plcp_jiffies); | ||
635 | priv->plcp_jiffies = plcp_received_jiffies; | ||
636 | /* | ||
637 | * check to make sure plcp_msec is not 0 to prevent division | ||
638 | * by zero. | ||
639 | */ | ||
640 | if (plcp_msec) { | ||
641 | combined_plcp_delta = | ||
642 | (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) - | ||
643 | le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) + | ||
644 | (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) - | ||
645 | le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err)); | ||
646 | |||
647 | if ((combined_plcp_delta > 0) && | ||
648 | ((combined_plcp_delta * 100) / plcp_msec) > | ||
649 | priv->cfg->plcp_delta_threshold) { | ||
650 | /* | ||
651 | * if plcp_err exceed the threshold, the following | ||
652 | * data is printed in csv format: | ||
653 | * Text: plcp_err exceeded %d, | ||
654 | * Received ofdm.plcp_err, | ||
655 | * Current ofdm.plcp_err, | ||
656 | * Received ofdm_ht.plcp_err, | ||
657 | * Current ofdm_ht.plcp_err, | ||
658 | * combined_plcp_delta, | ||
659 | * plcp_msec | ||
660 | */ | ||
661 | IWL_DEBUG_RADIO(priv, PLCP_MSG, | ||
662 | priv->cfg->plcp_delta_threshold, | ||
663 | le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err), | ||
664 | le32_to_cpu(priv->statistics.rx.ofdm.plcp_err), | ||
665 | le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err), | ||
666 | le32_to_cpu( | ||
667 | priv->statistics.rx.ofdm_ht.plcp_err), | ||
668 | combined_plcp_delta, plcp_msec); | ||
669 | |||
670 | /* | ||
671 | * Reset the RF radio due to the high plcp | ||
672 | * error rate | ||
673 | */ | ||
674 | iwl_force_rf_reset(priv); | ||
675 | } | ||
676 | } | ||
677 | |||
624 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); | 678 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); |
625 | 679 | ||
626 | set_bit(STATUS_STATISTICS, &priv->status); | 680 | set_bit(STATUS_STATISTICS, &priv->status); |