diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-1000.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-6000.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rx.c | 97 |
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 | ||
219 | static const struct iwl_ops iwl1000_ops = { | 220 | static 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 | ||
2227 | static const struct iwl_ops iwl4965_ops = { | 2227 | static 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 | ||
1506 | static struct iwl_lib_ops iwl5150_lib = { | 1507 | static 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 | ||
1562 | static const struct iwl_ops iwl5000_ops = { | 1564 | static 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 | ||
285 | static const struct iwl_ops iwl6000_ops = { | 286 | static 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 | ||
352 | static const struct iwl_ops iwl6050_ops = { | 354 | static 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); |
438 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | 441 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, |
439 | struct iwl_rx_mem_buffer *rxb); | 442 | struct iwl_rx_mem_buffer *rxb); |
440 | void iwl_recover_from_statistics(struct iwl_priv *priv, | 443 | bool iwl_good_plcp_health(struct iwl_priv *priv, |
444 | struct iwl_rx_packet *pkt); | ||
445 | bool iwl_good_ack_health(struct iwl_priv *priv, | ||
441 | struct iwl_rx_packet *pkt); | 446 | struct iwl_rx_packet *pkt); |
442 | void iwl_rx_statistics(struct iwl_priv *priv, | 447 | void 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 | */ |
634 | void iwl_recover_from_statistics(struct iwl_priv *priv, | 631 | bool 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 | } | ||
672 | EXPORT_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 | */ | ||
680 | bool 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 | } |
735 | EXPORT_SYMBOL(iwl_good_plcp_health); | ||
736 | |||
737 | static 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 | } |
729 | EXPORT_SYMBOL(iwl_recover_from_statistics); | ||
730 | 766 | ||
731 | void iwl_rx_statistics(struct iwl_priv *priv, | 767 | void 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 | ||