diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 67 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rx.c | 3 |
3 files changed, 69 insertions, 3 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index a4d842a05836..05d808b28777 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -390,6 +390,67 @@ static void iwl3945_accumulative_statistics(struct iwl_priv *priv, | |||
390 | } | 390 | } |
391 | #endif | 391 | #endif |
392 | 392 | ||
393 | /** | ||
394 | * iwl3945_good_plcp_health - checks for plcp error. | ||
395 | * | ||
396 | * When the plcp error is exceeding the thresholds, reset the radio | ||
397 | * to improve the throughput. | ||
398 | */ | ||
399 | static bool iwl3945_good_plcp_health(struct iwl_priv *priv, | ||
400 | struct iwl_rx_packet *pkt) | ||
401 | { | ||
402 | bool rc = true; | ||
403 | struct iwl3945_notif_statistics current_stat; | ||
404 | int combined_plcp_delta; | ||
405 | unsigned int plcp_msec; | ||
406 | unsigned long plcp_received_jiffies; | ||
407 | |||
408 | memcpy(¤t_stat, pkt->u.raw, sizeof(struct | ||
409 | iwl3945_notif_statistics)); | ||
410 | /* | ||
411 | * check for plcp_err and trigger radio reset if it exceeds | ||
412 | * the plcp error threshold plcp_delta. | ||
413 | */ | ||
414 | plcp_received_jiffies = jiffies; | ||
415 | plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies - | ||
416 | (long) priv->plcp_jiffies); | ||
417 | priv->plcp_jiffies = plcp_received_jiffies; | ||
418 | /* | ||
419 | * check to make sure plcp_msec is not 0 to prevent division | ||
420 | * by zero. | ||
421 | */ | ||
422 | if (plcp_msec) { | ||
423 | combined_plcp_delta = | ||
424 | (le32_to_cpu(current_stat.rx.ofdm.plcp_err) - | ||
425 | le32_to_cpu(priv->_3945.statistics.rx.ofdm.plcp_err)); | ||
426 | |||
427 | if ((combined_plcp_delta > 0) && | ||
428 | ((combined_plcp_delta * 100) / plcp_msec) > | ||
429 | priv->cfg->plcp_delta_threshold) { | ||
430 | /* | ||
431 | * if plcp_err exceed the threshold, the following | ||
432 | * data is printed in csv format: | ||
433 | * Text: plcp_err exceeded %d, | ||
434 | * Received ofdm.plcp_err, | ||
435 | * Current ofdm.plcp_err, | ||
436 | * combined_plcp_delta, | ||
437 | * plcp_msec | ||
438 | */ | ||
439 | IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " | ||
440 | "%u, %d, %u mSecs\n", | ||
441 | priv->cfg->plcp_delta_threshold, | ||
442 | le32_to_cpu(current_stat.rx.ofdm.plcp_err), | ||
443 | combined_plcp_delta, plcp_msec); | ||
444 | /* | ||
445 | * Reset the RF radio due to the high plcp | ||
446 | * error rate | ||
447 | */ | ||
448 | rc = false; | ||
449 | } | ||
450 | } | ||
451 | return rc; | ||
452 | } | ||
453 | |||
393 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | 454 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, |
394 | struct iwl_rx_mem_buffer *rxb) | 455 | struct iwl_rx_mem_buffer *rxb) |
395 | { | 456 | { |
@@ -401,6 +462,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | |||
401 | #ifdef CONFIG_IWLWIFI_DEBUG | 462 | #ifdef CONFIG_IWLWIFI_DEBUG |
402 | iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw); | 463 | iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw); |
403 | #endif | 464 | #endif |
465 | iwl_recover_from_statistics(priv, pkt); | ||
404 | 466 | ||
405 | memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics)); | 467 | memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics)); |
406 | } | 468 | } |
@@ -2792,6 +2854,7 @@ static struct iwl_lib_ops iwl3945_lib = { | |||
2792 | .config_ap = iwl3945_config_ap, | 2854 | .config_ap = iwl3945_config_ap, |
2793 | .manage_ibss_station = iwl3945_manage_ibss_station, | 2855 | .manage_ibss_station = iwl3945_manage_ibss_station, |
2794 | .add_bcast_station = iwl3945_add_bcast_station, | 2856 | .add_bcast_station = iwl3945_add_bcast_station, |
2857 | .check_plcp_health = iwl3945_good_plcp_health, | ||
2795 | 2858 | ||
2796 | .debugfs_ops = { | 2859 | .debugfs_ops = { |
2797 | .rx_stats_read = iwl3945_ucode_rx_stats_read, | 2860 | .rx_stats_read = iwl3945_ucode_rx_stats_read, |
@@ -2832,7 +2895,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { | |||
2832 | .ht_greenfield_support = false, | 2895 | .ht_greenfield_support = false, |
2833 | .led_compensation = 64, | 2896 | .led_compensation = 64, |
2834 | .broken_powersave = true, | 2897 | .broken_powersave = true, |
2835 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 2898 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
2836 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 2899 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
2837 | .max_event_log_size = 512, | 2900 | .max_event_log_size = 512, |
2838 | .tx_power_by_driver = true, | 2901 | .tx_power_by_driver = true, |
@@ -2853,7 +2916,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { | |||
2853 | .ht_greenfield_support = false, | 2916 | .ht_greenfield_support = false, |
2854 | .led_compensation = 64, | 2917 | .led_compensation = 64, |
2855 | .broken_powersave = true, | 2918 | .broken_powersave = true, |
2856 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 2919 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
2857 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 2920 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
2858 | .max_event_log_size = 512, | 2921 | .max_event_log_size = 512, |
2859 | .tx_power_by_driver = true, | 2922 | .tx_power_by_driver = true, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 2f664a3f0484..7a3f94926c25 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -441,6 +441,8 @@ bool iwl_good_plcp_health(struct iwl_priv *priv, | |||
441 | struct iwl_rx_packet *pkt); | 441 | struct iwl_rx_packet *pkt); |
442 | bool iwl_good_ack_health(struct iwl_priv *priv, | 442 | bool iwl_good_ack_health(struct iwl_priv *priv, |
443 | struct iwl_rx_packet *pkt); | 443 | struct iwl_rx_packet *pkt); |
444 | void iwl_recover_from_statistics(struct iwl_priv *priv, | ||
445 | struct iwl_rx_packet *pkt); | ||
444 | void iwl_rx_statistics(struct iwl_priv *priv, | 446 | void iwl_rx_statistics(struct iwl_priv *priv, |
445 | struct iwl_rx_mem_buffer *rxb); | 447 | struct iwl_rx_mem_buffer *rxb); |
446 | void iwl_reply_statistics(struct iwl_priv *priv, | 448 | void iwl_reply_statistics(struct iwl_priv *priv, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index d661fce000c2..c7c8d8a43eb3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -397,7 +397,7 @@ bool iwl_good_plcp_health(struct iwl_priv *priv, | |||
397 | } | 397 | } |
398 | EXPORT_SYMBOL(iwl_good_plcp_health); | 398 | EXPORT_SYMBOL(iwl_good_plcp_health); |
399 | 399 | ||
400 | static void iwl_recover_from_statistics(struct iwl_priv *priv, | 400 | void iwl_recover_from_statistics(struct iwl_priv *priv, |
401 | struct iwl_rx_packet *pkt) | 401 | struct iwl_rx_packet *pkt) |
402 | { | 402 | { |
403 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 403 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
@@ -428,6 +428,7 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv, | |||
428 | } | 428 | } |
429 | } | 429 | } |
430 | } | 430 | } |
431 | EXPORT_SYMBOL(iwl_recover_from_statistics); | ||
431 | 432 | ||
432 | void iwl_rx_statistics(struct iwl_priv *priv, | 433 | void iwl_rx_statistics(struct iwl_priv *priv, |
433 | struct iwl_rx_mem_buffer *rxb) | 434 | struct iwl_rx_mem_buffer *rxb) |