aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-rx.c
diff options
context:
space:
mode:
authorStanislaw Gruszka <sgruszka@redhat.com>2011-03-04 11:51:51 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-03-04 14:06:50 -0500
commit410f2bb30d27252cc55a5f41668de60de62e5dc8 (patch)
treedb98f25482b239015fd7ec5027c971fca60ecce3 /drivers/net/wireless/iwlwifi/iwl-rx.c
parent6198c387b25b528fd89a48bf67f0402d828ffa18 (diff)
iwlwifi: avoid too frequent recover from statistics
Usually H/W generate statistics notify once per about 100ms, but sometimes we can receive notify in shorter time, even 2 ms. This can be problem for plcp health and ack health checking. I.e. with 2 plcp errors happens randomly in 2 ms duration, we exceed plcp delta threshold equal to 100 (2*100/2). Also checking ack's in short time, can results not necessary false positive and firmware reset, for example when channel is noised and we do not receive ACKs frames or when remote device does not send ACKs at the moment. Patch change code to do statistic check and possible recovery only if 99ms elapsed from last check. Forced delay should assure we have good statistic data to estimate hardware state. Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> Acked-by: Wey-Yi Guy <wey-yi.w.guy@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.c46
1 files changed, 26 insertions, 20 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index a70f1eb08e5c..7dc2d39e5cd6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -449,10 +449,8 @@ static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt
449 * to improve the throughput. 449 * to improve the throughput.
450 */ 450 */
451static bool iwl_good_plcp_health(struct iwl_priv *priv, 451static bool iwl_good_plcp_health(struct iwl_priv *priv,
452 struct iwl_rx_packet *pkt) 452 struct iwl_rx_packet *pkt, unsigned int msecs)
453{ 453{
454 unsigned int msecs;
455 unsigned long stamp;
456 int delta; 454 int delta;
457 int threshold = priv->cfg->base_params->plcp_delta_threshold; 455 int threshold = priv->cfg->base_params->plcp_delta_threshold;
458 456
@@ -461,13 +459,6 @@ static bool iwl_good_plcp_health(struct iwl_priv *priv,
461 return true; 459 return true;
462 } 460 }
463 461
464 stamp = jiffies;
465 msecs = jiffies_to_msecs(stamp - priv->plcp_jiffies);
466 priv->plcp_jiffies = stamp;
467
468 if (msecs == 0)
469 return true;
470
471 if (iwl_bt_statistics(priv)) { 462 if (iwl_bt_statistics(priv)) {
472 struct statistics_rx_bt *cur, *old; 463 struct statistics_rx_bt *cur, *old;
473 464
@@ -508,9 +499,21 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv,
508 struct iwl_rx_packet *pkt) 499 struct iwl_rx_packet *pkt)
509{ 500{
510 const struct iwl_mod_params *mod_params = priv->cfg->mod_params; 501 const struct iwl_mod_params *mod_params = priv->cfg->mod_params;
502 unsigned int msecs;
503 unsigned long stamp;
511 504
512 if (test_bit(STATUS_EXIT_PENDING, &priv->status) || 505 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
513 !iwl_is_any_associated(priv)) 506 return;
507
508 stamp = jiffies;
509 msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies);
510
511 /* Only gather statistics and update time stamp when not associated */
512 if (!iwl_is_any_associated(priv))
513 goto out;
514
515 /* Do not check/recover when do not have enough statistics data */
516 if (msecs < 99)
514 return; 517 return;
515 518
516 if (mod_params->ack_check && !iwl_good_ack_health(priv, pkt)) { 519 if (mod_params->ack_check && !iwl_good_ack_health(priv, pkt)) {
@@ -519,8 +522,18 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv,
519 return; 522 return;
520 } 523 }
521 524
522 if (mod_params->plcp_check && !iwl_good_plcp_health(priv, pkt)) 525 if (mod_params->plcp_check && !iwl_good_plcp_health(priv, pkt, msecs))
523 iwl_force_reset(priv, IWL_RF_RESET, false); 526 iwl_force_reset(priv, IWL_RF_RESET, false);
527
528out:
529 if (iwl_bt_statistics(priv))
530 memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt,
531 sizeof(priv->_agn.statistics_bt));
532 else
533 memcpy(&priv->_agn.statistics, &pkt->u.stats,
534 sizeof(priv->_agn.statistics));
535
536 priv->rx_statistics_jiffies = stamp;
524} 537}
525 538
526/* Calculate noise level, based on measurements during network silence just 539/* Calculate noise level, based on measurements during network silence just
@@ -669,13 +682,6 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
669 682
670 iwl_recover_from_statistics(priv, pkt); 683 iwl_recover_from_statistics(priv, pkt);
671 684
672 if (iwl_bt_statistics(priv))
673 memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt,
674 sizeof(priv->_agn.statistics_bt));
675 else
676 memcpy(&priv->_agn.statistics, &pkt->u.stats,
677 sizeof(priv->_agn.statistics));
678
679 set_bit(STATUS_STATISTICS, &priv->status); 685 set_bit(STATUS_STATISTICS, &priv->status);
680 686
681 /* Reschedule the statistics timer to occur in 687 /* Reschedule the statistics timer to occur in