aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-rx.c
diff options
context:
space:
mode:
authorTrieu 'Andrew' Nguyen <trieux.t.nguyen@intel.com>2010-01-22 17:22:46 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-01-25 16:36:21 -0500
commit3e4fb5faefb57824f2e42305b3d5907845af978c (patch)
treea9cb64dff2fea16e290ab29eb4260c973d52e88f /drivers/net/wireless/iwlwifi/iwl-rx.c
parentd4d59e88cb746165c6fe33eacb6f582d525c6ef1 (diff)
iwlwifi: Tune radio to prevent unexpected behavior
We have seen the throughput dropped due to external noisy environment and the radio is out of tune. There are lot of plcp errors indicating this condition. Eventually the station can get de-authenticated by the Access Point. By resetting and tuning the radio, the plcp errors are reduced or eliminated and the throughput starts to rise. To prevent unexpected behavior such as drop in throughput or deauthentication, - The change provides the driver feature to monitor and tune the radio base on the statistics notification from the uCode. - It also allows the setting of the plcp error rate threshold via the plcp_delta under debugfs interface. Signed-off-by: Trieu 'Andrew' Nguyen <trieux.t.nguyen@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-rx.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c54
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"
605void iwl_rx_statistics(struct iwl_priv *priv, 606void 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);