aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-rx.c
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2010-03-05 17:22:46 -0500
committerReinette Chatre <reinette.chatre@intel.com>2010-03-19 16:41:26 -0400
commitfa8f130c504223d25c116b3d23787f465dfb1317 (patch)
tree3e7fba50666c23d0e534fe0ea08397d1fe35f2c7 /drivers/net/wireless/iwlwifi/iwl-rx.c
parentd5a0ffa3eaf9e898f25a925813f1a723be7808f8 (diff)
iwlwifi: code cleanup for connectivity recovery
Split the connectivity check and recovery routine into separated functions based on the types 1. iwl_good_ack_health() - check for ack count 2. iwl_good_plcp_health() - check for plcp error Based on the type of errors being detected, different recovery methods will be used to bring the system back to normal operational state. Because different NIC has different HW and uCode, the behavior is also different; these functions thus now form part of the ops infrastructure, so we can have more control on how to monitor and recover from error condition case per device. Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-rx.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c97
1 files changed, 66 insertions, 31 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 7aef285d2818..b6a64d83718a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -621,24 +621,18 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,
621#define BA_TIMEOUT_CNT (5) 621#define BA_TIMEOUT_CNT (5)
622#define BA_TIMEOUT_MAX (16) 622#define BA_TIMEOUT_MAX (16)
623 623
624#define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" 624/**
625/* 625 * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries.
626 * This function checks for plcp error, ACK count ratios, aggregated BA 626 *
627 * timeout retries. 627 * When the ACK count ratio is 0 and aggregated BA timeout retries exceeding
628 * - When the ACK count ratio is 0 and aggregated BA timeout retries is 628 * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal
629 * exceeding the BA_TIMEOUT_MAX, it will recover the failure by resetting 629 * operation state.
630 * the firmware.
631 * - When the plcp error is exceeding the thresholds, it will reset the radio
632 * to improve the throughput.
633 */ 630 */
634void iwl_recover_from_statistics(struct iwl_priv *priv, 631bool iwl_good_ack_health(struct iwl_priv *priv,
635 struct iwl_rx_packet *pkt) 632 struct iwl_rx_packet *pkt)
636{ 633{
637 int combined_plcp_delta; 634 bool rc = true;
638 unsigned int plcp_msec; 635 int actual_ack_cnt_delta, expected_ack_cnt_delta;
639 unsigned long plcp_received_jiffies;
640 int actual_ack_cnt_delta;
641 int expected_ack_cnt_delta;
642 int ba_timeout_delta; 636 int ba_timeout_delta;
643 637
644 actual_ack_cnt_delta = 638 actual_ack_cnt_delta =
@@ -669,13 +663,27 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
669#endif 663#endif
670 IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", 664 IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
671 ba_timeout_delta); 665 ba_timeout_delta);
672 if ((actual_ack_cnt_delta == 0) && 666 if (!actual_ack_cnt_delta &&
673 (ba_timeout_delta >= BA_TIMEOUT_MAX)) { 667 (ba_timeout_delta >= BA_TIMEOUT_MAX))
674 IWL_DEBUG_RADIO(priv, 668 rc = false;
675 "call iwl_force_reset(IWL_FW_RESET)\n");
676 iwl_force_reset(priv, IWL_FW_RESET);
677 }
678 } 669 }
670 return rc;
671}
672EXPORT_SYMBOL(iwl_good_ack_health);
673
674/**
675 * iwl_good_plcp_health - checks for plcp error.
676 *
677 * When the plcp error is exceeding the thresholds, reset the radio
678 * to improve the throughput.
679 */
680bool iwl_good_plcp_health(struct iwl_priv *priv,
681 struct iwl_rx_packet *pkt)
682{
683 bool rc = true;
684 int combined_plcp_delta;
685 unsigned int plcp_msec;
686 unsigned long plcp_received_jiffies;
679 687
680 /* 688 /*
681 * check for plcp_err and trigger radio reset if it exceeds 689 * check for plcp_err and trigger radio reset if it exceeds
@@ -710,7 +718,8 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
710 * combined_plcp_delta, 718 * combined_plcp_delta,
711 * plcp_msec 719 * plcp_msec
712 */ 720 */
713 IWL_DEBUG_RADIO(priv, PLCP_MSG, 721 IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
722 "%u, %u, %u, %u, %d, %u mSecs\n",
714 priv->cfg->plcp_delta_threshold, 723 priv->cfg->plcp_delta_threshold,
715 le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err), 724 le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
716 le32_to_cpu(priv->statistics.rx.ofdm.plcp_err), 725 le32_to_cpu(priv->statistics.rx.ofdm.plcp_err),
@@ -718,15 +727,42 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
718 le32_to_cpu( 727 le32_to_cpu(
719 priv->statistics.rx.ofdm_ht.plcp_err), 728 priv->statistics.rx.ofdm_ht.plcp_err),
720 combined_plcp_delta, plcp_msec); 729 combined_plcp_delta, plcp_msec);
721 /* 730 rc = false;
722 * Reset the RF radio due to the high plcp 731 }
723 * error rate 732 }
724 */ 733 return rc;
725 iwl_force_reset(priv, IWL_RF_RESET); 734}
735EXPORT_SYMBOL(iwl_good_plcp_health);
736
737static void iwl_recover_from_statistics(struct iwl_priv *priv,
738 struct iwl_rx_packet *pkt)
739{
740 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
741 return;
742 if (iwl_is_associated(priv)) {
743 if (priv->cfg->ops->lib->check_ack_health) {
744 if (!priv->cfg->ops->lib->check_ack_health(
745 priv, pkt)) {
746 /*
747 * low ack count detected
748 * restart Firmware
749 */
750 IWL_ERR(priv, "low ack count detected, "
751 "restart firmware\n");
752 iwl_force_reset(priv, IWL_FW_RESET);
753 }
754 } else if (priv->cfg->ops->lib->check_plcp_health) {
755 if (!priv->cfg->ops->lib->check_plcp_health(
756 priv, pkt)) {
757 /*
758 * high plcp error detected
759 * reset Radio
760 */
761 iwl_force_reset(priv, IWL_RF_RESET);
762 }
726 } 763 }
727 } 764 }
728} 765}
729EXPORT_SYMBOL(iwl_recover_from_statistics);
730 766
731void iwl_rx_statistics(struct iwl_priv *priv, 767void iwl_rx_statistics(struct iwl_priv *priv,
732 struct iwl_rx_mem_buffer *rxb) 768 struct iwl_rx_mem_buffer *rxb)
@@ -748,8 +784,7 @@ void iwl_rx_statistics(struct iwl_priv *priv,
748#ifdef CONFIG_IWLWIFI_DEBUG 784#ifdef CONFIG_IWLWIFI_DEBUG
749 iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); 785 iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
750#endif 786#endif
751 if (priv->cfg->ops->lib->recover_from_statistics) 787 iwl_recover_from_statistics(priv, pkt);
752 priv->cfg->ops->lib->recover_from_statistics(priv, pkt);
753 788
754 memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); 789 memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
755 790