aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c97
6 files changed, 85 insertions, 40 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index c6d6a0c2cd3..9e392896005 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -213,7 +213,8 @@ static struct iwl_lib_ops iwl1000_lib = {
213 }, 213 },
214 .add_bcast_station = iwl_add_bcast_station, 214 .add_bcast_station = iwl_add_bcast_station,
215 .recover_from_tx_stall = iwl_bg_monitor_recover, 215 .recover_from_tx_stall = iwl_bg_monitor_recover,
216 .recover_from_statistics = iwl_recover_from_statistics, 216 .check_plcp_health = iwl_good_plcp_health,
217 .check_ack_health = iwl_good_ack_health,
217}; 218};
218 219
219static const struct iwl_ops iwl1000_ops = { 220static const struct iwl_ops iwl1000_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 5efd60a5b98..3949133d9ee 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2221,7 +2221,7 @@ static struct iwl_lib_ops iwl4965_lib = {
2221 .set_ct_kill = iwl4965_set_ct_threshold, 2221 .set_ct_kill = iwl4965_set_ct_threshold,
2222 }, 2222 },
2223 .add_bcast_station = iwl_add_bcast_station, 2223 .add_bcast_station = iwl_add_bcast_station,
2224 .recover_from_statistics = iwl_recover_from_statistics, 2224 .check_plcp_health = iwl_good_plcp_health,
2225}; 2225};
2226 2226
2227static const struct iwl_ops iwl4965_ops = { 2227static const struct iwl_ops iwl4965_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 75f2a5156be..2267cad49cb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -1500,7 +1500,8 @@ struct iwl_lib_ops iwl5000_lib = {
1500 }, 1500 },
1501 .add_bcast_station = iwl_add_bcast_station, 1501 .add_bcast_station = iwl_add_bcast_station,
1502 .recover_from_tx_stall = iwl_bg_monitor_recover, 1502 .recover_from_tx_stall = iwl_bg_monitor_recover,
1503 .recover_from_statistics = iwl_recover_from_statistics, 1503 .check_plcp_health = iwl_good_plcp_health,
1504 .check_ack_health = iwl_good_ack_health,
1504}; 1505};
1505 1506
1506static struct iwl_lib_ops iwl5150_lib = { 1507static struct iwl_lib_ops iwl5150_lib = {
@@ -1556,7 +1557,8 @@ static struct iwl_lib_ops iwl5150_lib = {
1556 }, 1557 },
1557 .add_bcast_station = iwl_add_bcast_station, 1558 .add_bcast_station = iwl_add_bcast_station,
1558 .recover_from_tx_stall = iwl_bg_monitor_recover, 1559 .recover_from_tx_stall = iwl_bg_monitor_recover,
1559 .recover_from_statistics = iwl_recover_from_statistics, 1560 .check_plcp_health = iwl_good_plcp_health,
1561 .check_ack_health = iwl_good_ack_health,
1560}; 1562};
1561 1563
1562static const struct iwl_ops iwl5000_ops = { 1564static const struct iwl_ops iwl5000_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index b1f0e5c7e28..d75799946a7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -279,7 +279,8 @@ static struct iwl_lib_ops iwl6000_lib = {
279 }, 279 },
280 .add_bcast_station = iwl_add_bcast_station, 280 .add_bcast_station = iwl_add_bcast_station,
281 .recover_from_tx_stall = iwl_bg_monitor_recover, 281 .recover_from_tx_stall = iwl_bg_monitor_recover,
282 .recover_from_statistics = iwl_recover_from_statistics, 282 .check_plcp_health = iwl_good_plcp_health,
283 .check_ack_health = iwl_good_ack_health,
283}; 284};
284 285
285static const struct iwl_ops iwl6000_ops = { 286static const struct iwl_ops iwl6000_ops = {
@@ -346,7 +347,8 @@ static struct iwl_lib_ops iwl6050_lib = {
346 }, 347 },
347 .add_bcast_station = iwl_add_bcast_station, 348 .add_bcast_station = iwl_add_bcast_station,
348 .recover_from_tx_stall = iwl_bg_monitor_recover, 349 .recover_from_tx_stall = iwl_bg_monitor_recover,
349 .recover_from_statistics = iwl_recover_from_statistics, 350 .check_plcp_health = iwl_good_plcp_health,
351 .check_ack_health = iwl_good_ack_health,
350}; 352};
351 353
352static const struct iwl_ops iwl6050_ops = { 354static const struct iwl_ops iwl6050_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 4251afb8bf5..b3e698b576e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -193,8 +193,11 @@ struct iwl_lib_ops {
193 void (*add_bcast_station)(struct iwl_priv *priv); 193 void (*add_bcast_station)(struct iwl_priv *priv);
194 /* recover from tx queue stall */ 194 /* recover from tx queue stall */
195 void (*recover_from_tx_stall)(unsigned long data); 195 void (*recover_from_tx_stall)(unsigned long data);
196 /* recover from errors showed in statistics */ 196 /* check for plcp health */
197 void (*recover_from_statistics)(struct iwl_priv *priv, 197 bool (*check_plcp_health)(struct iwl_priv *priv,
198 struct iwl_rx_packet *pkt);
199 /* check for ack health */
200 bool (*check_ack_health)(struct iwl_priv *priv,
198 struct iwl_rx_packet *pkt); 201 struct iwl_rx_packet *pkt);
199}; 202};
200 203
@@ -437,7 +440,9 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
437 struct iwl_rx_mem_buffer *rxb); 440 struct iwl_rx_mem_buffer *rxb);
438void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, 441void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
439 struct iwl_rx_mem_buffer *rxb); 442 struct iwl_rx_mem_buffer *rxb);
440void iwl_recover_from_statistics(struct iwl_priv *priv, 443bool iwl_good_plcp_health(struct iwl_priv *priv,
444 struct iwl_rx_packet *pkt);
445bool iwl_good_ack_health(struct iwl_priv *priv,
441 struct iwl_rx_packet *pkt); 446 struct iwl_rx_packet *pkt);
442void iwl_rx_statistics(struct iwl_priv *priv, 447void iwl_rx_statistics(struct iwl_priv *priv,
443 struct iwl_rx_mem_buffer *rxb); 448 struct iwl_rx_mem_buffer *rxb);
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 7aef285d281..b6a64d83718 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