aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c111
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c24
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c21
13 files changed, 91 insertions, 138 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index fb3e3713bae4..3c983e426f25 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -228,7 +228,6 @@ static struct iwl_lib_ops iwl1000_lib = {
228 .bt_stats_read = iwl_ucode_bt_stats_read, 228 .bt_stats_read = iwl_ucode_bt_stats_read,
229 .reply_tx_error = iwl_reply_tx_error_read, 229 .reply_tx_error = iwl_reply_tx_error_read,
230 }, 230 },
231 .recover_from_tx_stall = iwl_bg_monitor_recover,
232 .check_plcp_health = iwl_good_plcp_health, 231 .check_plcp_health = iwl_good_plcp_health,
233 .check_ack_health = iwl_good_ack_health, 232 .check_ack_health = iwl_good_ack_health,
234 .txfifo_flush = iwlagn_txfifo_flush, 233 .txfifo_flush = iwlagn_txfifo_flush,
@@ -262,7 +261,7 @@ static struct iwl_base_params iwl1000_base_params = {
262 .support_ct_kill_exit = true, 261 .support_ct_kill_exit = true,
263 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, 262 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
264 .chain_noise_scale = 1000, 263 .chain_noise_scale = 1000,
265 .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, 264 .wd_timeout = IWL_DEF_WD_TIMEOUT,
266 .max_event_log_size = 128, 265 .max_event_log_size = 128,
267 .ucode_tracing = true, 266 .ucode_tracing = true,
268 .sensitivity_calib_by_driver = true, 267 .sensitivity_calib_by_driver = true,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index cac9647da71c..a9b852be4509 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -325,6 +325,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
325 return; 325 return;
326 } 326 }
327 327
328 txq->time_stamp = jiffies;
328 info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); 329 info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
329 ieee80211_tx_info_clear_status(info); 330 ieee80211_tx_info_clear_status(info);
330 331
@@ -2733,7 +2734,6 @@ static struct iwl_lib_ops iwl3945_lib = {
2733 .isr_ops = { 2734 .isr_ops = {
2734 .isr = iwl_isr_legacy, 2735 .isr = iwl_isr_legacy,
2735 }, 2736 },
2736 .recover_from_tx_stall = iwl_bg_monitor_recover,
2737 .check_plcp_health = iwl3945_good_plcp_health, 2737 .check_plcp_health = iwl3945_good_plcp_health,
2738 2738
2739 .debugfs_ops = { 2739 .debugfs_ops = {
@@ -2776,7 +2776,7 @@ static struct iwl_base_params iwl3945_base_params = {
2776 .led_compensation = 64, 2776 .led_compensation = 64,
2777 .broken_powersave = true, 2777 .broken_powersave = true,
2778 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, 2778 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
2779 .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, 2779 .wd_timeout = IWL_DEF_WD_TIMEOUT,
2780 .max_event_log_size = 512, 2780 .max_event_log_size = 512,
2781 .tx_power_by_driver = true, 2781 .tx_power_by_driver = true,
2782}; 2782};
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 6788ceb37686..3f1e5f1bf847 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2198,6 +2198,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2198 return; 2198 return;
2199 } 2199 }
2200 2200
2201 txq->time_stamp = jiffies;
2201 info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); 2202 info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
2202 memset(&info->status, 0, sizeof(info->status)); 2203 memset(&info->status, 0, sizeof(info->status));
2203 2204
@@ -2554,7 +2555,6 @@ static struct iwl_lib_ops iwl4965_lib = {
2554 .bt_stats_read = iwl_ucode_bt_stats_read, 2555 .bt_stats_read = iwl_ucode_bt_stats_read,
2555 .reply_tx_error = iwl_reply_tx_error_read, 2556 .reply_tx_error = iwl_reply_tx_error_read,
2556 }, 2557 },
2557 .recover_from_tx_stall = iwl_bg_monitor_recover,
2558 .check_plcp_health = iwl_good_plcp_health, 2558 .check_plcp_health = iwl_good_plcp_health,
2559}; 2559};
2560 2560
@@ -2609,7 +2609,7 @@ static struct iwl_base_params iwl4965_base_params = {
2609 .led_compensation = 61, 2609 .led_compensation = 61,
2610 .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, 2610 .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
2611 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, 2611 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
2612 .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, 2612 .wd_timeout = IWL_DEF_WD_TIMEOUT,
2613 .temperature_kelvin = true, 2613 .temperature_kelvin = true,
2614 .max_event_log_size = 512, 2614 .max_event_log_size = 512,
2615 .tx_power_by_driver = true, 2615 .tx_power_by_driver = true,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index cf74edb82a70..8435e5a4e69d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -402,7 +402,6 @@ static struct iwl_lib_ops iwl5000_lib = {
402 .bt_stats_read = iwl_ucode_bt_stats_read, 402 .bt_stats_read = iwl_ucode_bt_stats_read,
403 .reply_tx_error = iwl_reply_tx_error_read, 403 .reply_tx_error = iwl_reply_tx_error_read,
404 }, 404 },
405 .recover_from_tx_stall = iwl_bg_monitor_recover,
406 .check_plcp_health = iwl_good_plcp_health, 405 .check_plcp_health = iwl_good_plcp_health,
407 .check_ack_health = iwl_good_ack_health, 406 .check_ack_health = iwl_good_ack_health,
408 .txfifo_flush = iwlagn_txfifo_flush, 407 .txfifo_flush = iwlagn_txfifo_flush,
@@ -472,7 +471,6 @@ static struct iwl_lib_ops iwl5150_lib = {
472 .bt_stats_read = iwl_ucode_bt_stats_read, 471 .bt_stats_read = iwl_ucode_bt_stats_read,
473 .reply_tx_error = iwl_reply_tx_error_read, 472 .reply_tx_error = iwl_reply_tx_error_read,
474 }, 473 },
475 .recover_from_tx_stall = iwl_bg_monitor_recover,
476 .check_plcp_health = iwl_good_plcp_health, 474 .check_plcp_health = iwl_good_plcp_health,
477 .check_ack_health = iwl_good_ack_health, 475 .check_ack_health = iwl_good_ack_health,
478 .txfifo_flush = iwlagn_txfifo_flush, 476 .txfifo_flush = iwlagn_txfifo_flush,
@@ -511,7 +509,7 @@ static struct iwl_base_params iwl5000_base_params = {
511 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, 509 .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
512 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, 510 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
513 .chain_noise_scale = 1000, 511 .chain_noise_scale = 1000,
514 .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, 512 .wd_timeout = IWL_LONG_WD_TIMEOUT,
515 .max_event_log_size = 512, 513 .max_event_log_size = 512,
516 .ucode_tracing = true, 514 .ucode_tracing = true,
517 .sensitivity_calib_by_driver = true, 515 .sensitivity_calib_by_driver = true,
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 8018f38d5165..808942cc2991 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -339,7 +339,6 @@ static struct iwl_lib_ops iwl6000_lib = {
339 .bt_stats_read = iwl_ucode_bt_stats_read, 339 .bt_stats_read = iwl_ucode_bt_stats_read,
340 .reply_tx_error = iwl_reply_tx_error_read, 340 .reply_tx_error = iwl_reply_tx_error_read,
341 }, 341 },
342 .recover_from_tx_stall = iwl_bg_monitor_recover,
343 .check_plcp_health = iwl_good_plcp_health, 342 .check_plcp_health = iwl_good_plcp_health,
344 .check_ack_health = iwl_good_ack_health, 343 .check_ack_health = iwl_good_ack_health,
345 .txfifo_flush = iwlagn_txfifo_flush, 344 .txfifo_flush = iwlagn_txfifo_flush,
@@ -412,7 +411,6 @@ static struct iwl_lib_ops iwl6000g2b_lib = {
412 .bt_stats_read = iwl_ucode_bt_stats_read, 411 .bt_stats_read = iwl_ucode_bt_stats_read,
413 .reply_tx_error = iwl_reply_tx_error_read, 412 .reply_tx_error = iwl_reply_tx_error_read,
414 }, 413 },
415 .recover_from_tx_stall = iwl_bg_monitor_recover,
416 .check_plcp_health = iwl_good_plcp_health, 414 .check_plcp_health = iwl_good_plcp_health,
417 .check_ack_health = iwl_good_ack_health, 415 .check_ack_health = iwl_good_ack_health,
418 .txfifo_flush = iwlagn_txfifo_flush, 416 .txfifo_flush = iwlagn_txfifo_flush,
@@ -482,7 +480,7 @@ static struct iwl_base_params iwl6000_base_params = {
482 .support_ct_kill_exit = true, 480 .support_ct_kill_exit = true,
483 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, 481 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
484 .chain_noise_scale = 1000, 482 .chain_noise_scale = 1000,
485 .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, 483 .wd_timeout = IWL_DEF_WD_TIMEOUT,
486 .max_event_log_size = 512, 484 .max_event_log_size = 512,
487 .ucode_tracing = true, 485 .ucode_tracing = true,
488 .sensitivity_calib_by_driver = true, 486 .sensitivity_calib_by_driver = true,
@@ -506,7 +504,7 @@ static struct iwl_base_params iwl6050_base_params = {
506 .support_ct_kill_exit = true, 504 .support_ct_kill_exit = true,
507 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, 505 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
508 .chain_noise_scale = 1500, 506 .chain_noise_scale = 1500,
509 .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, 507 .wd_timeout = IWL_DEF_WD_TIMEOUT,
510 .max_event_log_size = 1024, 508 .max_event_log_size = 1024,
511 .ucode_tracing = true, 509 .ucode_tracing = true,
512 .sensitivity_calib_by_driver = true, 510 .sensitivity_calib_by_driver = true,
@@ -529,7 +527,7 @@ static struct iwl_base_params iwl6000_coex_base_params = {
529 .support_ct_kill_exit = true, 527 .support_ct_kill_exit = true,
530 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, 528 .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
531 .chain_noise_scale = 1000, 529 .chain_noise_scale = 1000,
532 .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, 530 .wd_timeout = IWL_LONG_WD_TIMEOUT,
533 .max_event_log_size = 512, 531 .max_event_log_size = 512,
534 .ucode_tracing = true, 532 .ucode_tracing = true,
535 .sensitivity_calib_by_driver = true, 533 .sensitivity_calib_by_driver = true,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 407f0bb8422a..d941910e7ef4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -405,6 +405,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
405 return; 405 return;
406 } 406 }
407 407
408 txq->time_stamp = jiffies;
408 info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); 409 info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
409 memset(&info->status, 0, sizeof(info->status)); 410 memset(&info->status, 0, sizeof(info->status));
410 411
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 32ab4a0215a0..d4075476670a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2654,13 +2654,8 @@ static void iwl_alive_start(struct iwl_priv *priv)
2654 /* After the ALIVE response, we can send host commands to the uCode */ 2654 /* After the ALIVE response, we can send host commands to the uCode */
2655 set_bit(STATUS_ALIVE, &priv->status); 2655 set_bit(STATUS_ALIVE, &priv->status);
2656 2656
2657 if (priv->cfg->ops->lib->recover_from_tx_stall) { 2657 /* Enable watchdog to monitor the driver tx queues */
2658 /* Enable timer to monitor the driver queues */ 2658 iwl_setup_watchdog(priv);
2659 mod_timer(&priv->monitor_recover,
2660 jiffies +
2661 msecs_to_jiffies(
2662 priv->cfg->base_params->monitor_recover_period));
2663 }
2664 2659
2665 if (iwl_is_rfkill(priv)) 2660 if (iwl_is_rfkill(priv))
2666 return; 2661 return;
@@ -2755,8 +2750,7 @@ static void __iwl_down(struct iwl_priv *priv)
2755 2750
2756 /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set 2751 /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
2757 * to prevent rearm timer */ 2752 * to prevent rearm timer */
2758 if (priv->cfg->ops->lib->recover_from_tx_stall) 2753 del_timer_sync(&priv->watchdog);
2759 del_timer_sync(&priv->monitor_recover);
2760 2754
2761 iwl_clear_ucode_stations(priv, NULL); 2755 iwl_clear_ucode_stations(priv, NULL);
2762 iwl_dealloc_bcast_stations(priv); 2756 iwl_dealloc_bcast_stations(priv);
@@ -3742,12 +3736,9 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
3742 priv->ucode_trace.data = (unsigned long)priv; 3736 priv->ucode_trace.data = (unsigned long)priv;
3743 priv->ucode_trace.function = iwl_bg_ucode_trace; 3737 priv->ucode_trace.function = iwl_bg_ucode_trace;
3744 3738
3745 if (priv->cfg->ops->lib->recover_from_tx_stall) { 3739 init_timer(&priv->watchdog);
3746 init_timer(&priv->monitor_recover); 3740 priv->watchdog.data = (unsigned long)priv;
3747 priv->monitor_recover.data = (unsigned long)priv; 3741 priv->watchdog.function = iwl_bg_watchdog;
3748 priv->monitor_recover.function =
3749 priv->cfg->ops->lib->recover_from_tx_stall;
3750 }
3751 3742
3752 if (!priv->cfg->base_params->use_isr_legacy) 3743 if (!priv->cfg->base_params->use_isr_legacy)
3753 tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) 3744 tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index c41f5a878210..d62b92518417 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1894,77 +1894,58 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1894} 1894}
1895EXPORT_SYMBOL(iwl_mac_change_interface); 1895EXPORT_SYMBOL(iwl_mac_change_interface);
1896 1896
1897/**
1898 * iwl_bg_monitor_recover - Timer callback to check for stuck queue and recover
1899 *
1900 * During normal condition (no queue is stuck), the timer is continually set to
1901 * execute every monitor_recover_period milliseconds after the last timer
1902 * expired. When the queue read_ptr is at the same place, the timer is
1903 * shorten to 100mSecs. This is
1904 * 1) to reduce the chance that the read_ptr may wrap around (not stuck)
1905 * 2) to detect the stuck queues quicker before the station and AP can
1906 * disassociate each other.
1907 *
1908 * This function monitors all the tx queues and recover from it if any
1909 * of the queues are stuck.
1910 * 1. It first check the cmd queue for stuck conditions. If it is stuck,
1911 * it will recover by resetting the firmware and return.
1912 * 2. Then, it checks for station association. If it associates it will check
1913 * other queues. If any queue is stuck, it will recover by resetting
1914 * the firmware.
1915 * Note: It the number of times the queue read_ptr to be at the same place to
1916 * be MAX_REPEAT+1 in order to consider to be stuck.
1917 */
1918/* 1897/*
1919 * The maximum number of times the read pointer of the tx queue at the 1898 * On every watchdog tick we check (latest) time stamp. If it does not
1920 * same place without considering to be stuck. 1899 * change during timeout period and queue is not empty we reset firmware.
1921 */ 1900 */
1922#define MAX_REPEAT (2)
1923static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt) 1901static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt)
1924{ 1902{
1925 struct iwl_tx_queue *txq; 1903 struct iwl_tx_queue *txq = &priv->txq[cnt];
1926 struct iwl_queue *q; 1904 struct iwl_queue *q = &txq->q;
1905 unsigned long timeout;
1906 int ret;
1927 1907
1928 txq = &priv->txq[cnt]; 1908 if (q->read_ptr == q->write_ptr) {
1929 q = &txq->q; 1909 txq->time_stamp = jiffies;
1930 /* queue is empty, skip */
1931 if (q->read_ptr == q->write_ptr)
1932 return 0; 1910 return 0;
1911 }
1933 1912
1934 if (q->read_ptr == q->last_read_ptr) { 1913 timeout = txq->time_stamp +
1935 /* a queue has not been read from last time */ 1914 msecs_to_jiffies(priv->cfg->base_params->wd_timeout);
1936 if (q->repeat_same_read_ptr > MAX_REPEAT) { 1915
1937 IWL_ERR(priv, 1916 if (time_after(jiffies, timeout)) {
1938 "queue %d stuck %d time. Fw reload.\n", 1917 IWL_ERR(priv, "Queue %d stuck for %u ms.\n",
1939 q->id, q->repeat_same_read_ptr); 1918 q->id, priv->cfg->base_params->wd_timeout);
1940 q->repeat_same_read_ptr = 0; 1919 ret = iwl_force_reset(priv, IWL_FW_RESET, false);
1941 iwl_force_reset(priv, IWL_FW_RESET, false); 1920 return (ret == -EAGAIN) ? 0 : 1;
1942 } else {
1943 q->repeat_same_read_ptr++;
1944 IWL_DEBUG_RADIO(priv,
1945 "queue %d, not read %d time\n",
1946 q->id,
1947 q->repeat_same_read_ptr);
1948 mod_timer(&priv->monitor_recover,
1949 jiffies + msecs_to_jiffies(
1950 IWL_ONE_HUNDRED_MSECS));
1951 return 1;
1952 }
1953 } else {
1954 q->last_read_ptr = q->read_ptr;
1955 q->repeat_same_read_ptr = 0;
1956 } 1921 }
1922
1957 return 0; 1923 return 0;
1958} 1924}
1959 1925
1960void iwl_bg_monitor_recover(unsigned long data) 1926/*
1927 * Making watchdog tick be a quarter of timeout assure we will
1928 * discover the queue hung between timeout and 1.25*timeout
1929 */
1930#define IWL_WD_TICK(timeout) ((timeout) / 4)
1931
1932/*
1933 * Watchdog timer callback, we check each tx queue for stuck, if if hung
1934 * we reset the firmware. If everything is fine just rearm the timer.
1935 */
1936void iwl_bg_watchdog(unsigned long data)
1961{ 1937{
1962 struct iwl_priv *priv = (struct iwl_priv *)data; 1938 struct iwl_priv *priv = (struct iwl_priv *)data;
1963 int cnt; 1939 int cnt;
1940 unsigned long timeout;
1964 1941
1965 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 1942 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
1966 return; 1943 return;
1967 1944
1945 timeout = priv->cfg->base_params->wd_timeout;
1946 if (timeout == 0)
1947 return;
1948
1968 /* monitor and check for stuck cmd queue */ 1949 /* monitor and check for stuck cmd queue */
1969 if (iwl_check_stuck_queue(priv, priv->cmd_queue)) 1950 if (iwl_check_stuck_queue(priv, priv->cmd_queue))
1970 return; 1951 return;
@@ -1979,17 +1960,23 @@ void iwl_bg_monitor_recover(unsigned long data)
1979 return; 1960 return;
1980 } 1961 }
1981 } 1962 }
1982 if (priv->cfg->base_params->monitor_recover_period) { 1963
1983 /* 1964 mod_timer(&priv->watchdog, jiffies +
1984 * Reschedule the timer to occur in 1965 msecs_to_jiffies(IWL_WD_TICK(timeout)));
1985 * priv->cfg->base_params->monitor_recover_period
1986 */
1987 mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies(
1988 priv->cfg->base_params->monitor_recover_period));
1989 }
1990} 1966}
1991EXPORT_SYMBOL(iwl_bg_monitor_recover); 1967EXPORT_SYMBOL(iwl_bg_watchdog);
1968
1969void iwl_setup_watchdog(struct iwl_priv *priv)
1970{
1971 unsigned int timeout = priv->cfg->base_params->wd_timeout;
1992 1972
1973 if (timeout)
1974 mod_timer(&priv->watchdog,
1975 jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout)));
1976 else
1977 del_timer(&priv->watchdog);
1978}
1979EXPORT_SYMBOL(iwl_setup_watchdog);
1993 1980
1994/* 1981/*
1995 * extended beacon time format 1982 * extended beacon time format
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 808be731ecb7..568920ac982d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -210,8 +210,6 @@ struct iwl_lib_ops {
210 210
211 /* temperature */ 211 /* temperature */
212 struct iwl_temp_ops temp_ops; 212 struct iwl_temp_ops temp_ops;
213 /* recover from tx queue stall */
214 void (*recover_from_tx_stall)(unsigned long data);
215 /* check for plcp health */ 213 /* check for plcp health */
216 bool (*check_plcp_health)(struct iwl_priv *priv, 214 bool (*check_plcp_health)(struct iwl_priv *priv,
217 struct iwl_rx_packet *pkt); 215 struct iwl_rx_packet *pkt);
@@ -280,7 +278,7 @@ struct iwl_mod_params {
280 * @plcp_delta_threshold: plcp error rate threshold used to trigger 278 * @plcp_delta_threshold: plcp error rate threshold used to trigger
281 * radio tuning when there is a high receiving plcp error rate 279 * radio tuning when there is a high receiving plcp error rate
282 * @chain_noise_scale: default chain noise scale used for gain computation 280 * @chain_noise_scale: default chain noise scale used for gain computation
283 * @monitor_recover_period: default timer used to check stuck queues 281 * @wd_timeout: TX queues watchdog timeout
284 * @temperature_kelvin: temperature report by uCode in kelvin 282 * @temperature_kelvin: temperature report by uCode in kelvin
285 * @max_event_log_size: size of event log buffer size for ucode event logging 283 * @max_event_log_size: size of event log buffer size for ucode event logging
286 * @tx_power_by_driver: tx power calibration performed by driver 284 * @tx_power_by_driver: tx power calibration performed by driver
@@ -315,8 +313,7 @@ struct iwl_base_params {
315 const bool support_wimax_coexist; 313 const bool support_wimax_coexist;
316 u8 plcp_delta_threshold; 314 u8 plcp_delta_threshold;
317 s32 chain_noise_scale; 315 s32 chain_noise_scale;
318 /* timer period for monitor the driver queues */ 316 unsigned int wd_timeout;
319 u32 monitor_recover_period;
320 bool temperature_kelvin; 317 bool temperature_kelvin;
321 u32 max_event_log_size; 318 u32 max_event_log_size;
322 const bool tx_power_by_driver; 319 const bool tx_power_by_driver;
@@ -546,6 +543,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
546void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, 543void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
547 int slots_num, u32 txq_id); 544 int slots_num, u32 txq_id);
548void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); 545void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
546void iwl_setup_watchdog(struct iwl_priv *priv);
549/***************************************************** 547/*****************************************************
550 * TX power 548 * TX power
551 ****************************************************/ 549 ****************************************************/
@@ -625,7 +623,7 @@ static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
625 return pci_lnk_ctl; 623 return pci_lnk_ctl;
626} 624}
627 625
628void iwl_bg_monitor_recover(unsigned long data); 626void iwl_bg_watchdog(unsigned long data);
629u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval); 627u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval);
630__le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, 628__le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
631 u32 addon, u32 beacon_interval); 629 u32 addon, u32 beacon_interval);
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 3cc58420d445..d36836376e6b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -1534,32 +1534,26 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
1534 user_buf, count, ppos); 1534 user_buf, count, ppos);
1535} 1535}
1536 1536
1537static ssize_t iwl_dbgfs_monitor_period_write(struct file *file, 1537static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file,
1538 const char __user *user_buf, 1538 const char __user *user_buf,
1539 size_t count, loff_t *ppos) { 1539 size_t count, loff_t *ppos) {
1540 1540
1541 struct iwl_priv *priv = file->private_data; 1541 struct iwl_priv *priv = file->private_data;
1542 char buf[8]; 1542 char buf[8];
1543 int buf_size; 1543 int buf_size;
1544 int period; 1544 int timeout;
1545 1545
1546 memset(buf, 0, sizeof(buf)); 1546 memset(buf, 0, sizeof(buf));
1547 buf_size = min(count, sizeof(buf) - 1); 1547 buf_size = min(count, sizeof(buf) - 1);
1548 if (copy_from_user(buf, user_buf, buf_size)) 1548 if (copy_from_user(buf, user_buf, buf_size))
1549 return -EFAULT; 1549 return -EFAULT;
1550 if (sscanf(buf, "%d", &period) != 1) 1550 if (sscanf(buf, "%d", &timeout) != 1)
1551 return -EINVAL; 1551 return -EINVAL;
1552 if (period < 0 || period > IWL_MAX_MONITORING_PERIOD) 1552 if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT)
1553 priv->cfg->base_params->monitor_recover_period = 1553 timeout = IWL_DEF_WD_TIMEOUT;
1554 IWL_DEF_MONITORING_PERIOD;
1555 else
1556 priv->cfg->base_params->monitor_recover_period = period;
1557 1554
1558 if (priv->cfg->base_params->monitor_recover_period) 1555 priv->cfg->base_params->wd_timeout = timeout;
1559 mod_timer(&priv->monitor_recover, jiffies + msecs_to_jiffies( 1556 iwl_setup_watchdog(priv);
1560 priv->cfg->base_params->monitor_recover_period));
1561 else
1562 del_timer_sync(&priv->monitor_recover);
1563 return count; 1557 return count;
1564} 1558}
1565 1559
@@ -1686,7 +1680,7 @@ DEBUGFS_READ_FILE_OPS(rxon_flags);
1686DEBUGFS_READ_FILE_OPS(rxon_filter_flags); 1680DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
1687DEBUGFS_WRITE_FILE_OPS(txfifo_flush); 1681DEBUGFS_WRITE_FILE_OPS(txfifo_flush);
1688DEBUGFS_READ_FILE_OPS(ucode_bt_stats); 1682DEBUGFS_READ_FILE_OPS(ucode_bt_stats);
1689DEBUGFS_WRITE_FILE_OPS(monitor_period); 1683DEBUGFS_WRITE_FILE_OPS(wd_timeout);
1690DEBUGFS_READ_FILE_OPS(bt_traffic); 1684DEBUGFS_READ_FILE_OPS(bt_traffic);
1691DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); 1685DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
1692DEBUGFS_READ_FILE_OPS(reply_tx_error); 1686DEBUGFS_READ_FILE_OPS(reply_tx_error);
@@ -1763,7 +1757,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
1763 DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); 1757 DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR);
1764 DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); 1758 DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
1765 DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); 1759 DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
1766 DEBUGFS_ADD_FILE(monitor_period, dir_debug, S_IWUSR); 1760 DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
1767 if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) 1761 if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
1768 DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); 1762 DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
1769 if (priv->cfg->base_params->sensitivity_calib_by_driver) 1763 if (priv->cfg->base_params->sensitivity_calib_by_driver)
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index ea81ced13756..836f1816b110 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -129,9 +129,6 @@ struct iwl_queue {
129 int write_ptr; /* 1-st empty entry (index) host_w*/ 129 int write_ptr; /* 1-st empty entry (index) host_w*/
130 int read_ptr; /* last used entry (index) host_r*/ 130 int read_ptr; /* last used entry (index) host_r*/
131 /* use for monitoring and recovering the stuck queue */ 131 /* use for monitoring and recovering the stuck queue */
132 int last_read_ptr; /* storing the last read_ptr */
133 /* number of time read_ptr and last_read_ptr are the same */
134 u8 repeat_same_read_ptr;
135 dma_addr_t dma_addr; /* physical addr for BD's */ 132 dma_addr_t dma_addr; /* physical addr for BD's */
136 int n_window; /* safe queue window */ 133 int n_window; /* safe queue window */
137 u32 id; 134 u32 id;
@@ -155,6 +152,7 @@ struct iwl_tx_info {
155 * @meta: array of meta data for each command/tx buffer 152 * @meta: array of meta data for each command/tx buffer
156 * @dma_addr_cmd: physical address of cmd/tx buffer array 153 * @dma_addr_cmd: physical address of cmd/tx buffer array
157 * @txb: array of per-TFD driver data 154 * @txb: array of per-TFD driver data
155 * @time_stamp: time (in jiffies) of last read_ptr change
158 * @need_update: indicates need to update read/write index 156 * @need_update: indicates need to update read/write index
159 * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled 157 * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
160 * 158 *
@@ -170,6 +168,7 @@ struct iwl_tx_queue {
170 struct iwl_device_cmd **cmd; 168 struct iwl_device_cmd **cmd;
171 struct iwl_cmd_meta *meta; 169 struct iwl_cmd_meta *meta;
172 struct iwl_tx_info *txb; 170 struct iwl_tx_info *txb;
171 unsigned long time_stamp;
173 u8 need_update; 172 u8 need_update;
174 u8 sched_retry; 173 u8 sched_retry;
175 u8 active; 174 u8 active;
@@ -1104,11 +1103,10 @@ struct iwl_event_log {
1104#define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) 1103#define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3)
1105#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) 1104#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
1106 1105
1107/* timer constants use to monitor and recover stuck tx queues in mSecs */ 1106/* TX queue watchdog timeouts in mSecs */
1108#define IWL_DEF_MONITORING_PERIOD (1000) 1107#define IWL_DEF_WD_TIMEOUT (2000)
1109#define IWL_LONG_MONITORING_PERIOD (5000) 1108#define IWL_LONG_WD_TIMEOUT (10000)
1110#define IWL_ONE_HUNDRED_MSECS (100) 1109#define IWL_MAX_WD_TIMEOUT (120000)
1111#define IWL_MAX_MONITORING_PERIOD (60000)
1112 1110
1113/* BT Antenna Coupling Threshold (dB) */ 1111/* BT Antenna Coupling Threshold (dB) */
1114#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35) 1112#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35)
@@ -1544,7 +1542,7 @@ struct iwl_priv {
1544 struct work_struct run_time_calib_work; 1542 struct work_struct run_time_calib_work;
1545 struct timer_list statistics_periodic; 1543 struct timer_list statistics_periodic;
1546 struct timer_list ucode_trace; 1544 struct timer_list ucode_trace;
1547 struct timer_list monitor_recover; 1545 struct timer_list watchdog;
1548 bool hw_ready; 1546 bool hw_ready;
1549 1547
1550 struct iwl_event_log event_log; 1548 struct iwl_event_log event_log;
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 90659bcf5804..073b6ce6141c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -263,8 +263,6 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
263 q->high_mark = 2; 263 q->high_mark = 2;
264 264
265 q->write_ptr = q->read_ptr = 0; 265 q->write_ptr = q->read_ptr = 0;
266 q->last_read_ptr = 0;
267 q->repeat_same_read_ptr = 0;
268 266
269 return 0; 267 return 0;
270} 268}
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index cc282aa2f43c..371abbf60eac 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2509,13 +2509,8 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
2509 /* After the ALIVE response, we can send commands to 3945 uCode */ 2509 /* After the ALIVE response, we can send commands to 3945 uCode */
2510 set_bit(STATUS_ALIVE, &priv->status); 2510 set_bit(STATUS_ALIVE, &priv->status);
2511 2511
2512 if (priv->cfg->ops->lib->recover_from_tx_stall) { 2512 /* Enable watchdog to monitor the driver tx queues */
2513 /* Enable timer to monitor the driver queues */ 2513 iwl_setup_watchdog(priv);
2514 mod_timer(&priv->monitor_recover,
2515 jiffies +
2516 msecs_to_jiffies(
2517 priv->cfg->base_params->monitor_recover_period));
2518 }
2519 2514
2520 if (iwl_is_rfkill(priv)) 2515 if (iwl_is_rfkill(priv))
2521 return; 2516 return;
@@ -2572,8 +2567,7 @@ static void __iwl3945_down(struct iwl_priv *priv)
2572 2567
2573 /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set 2568 /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
2574 * to prevent rearm timer */ 2569 * to prevent rearm timer */
2575 if (priv->cfg->ops->lib->recover_from_tx_stall) 2570 del_timer_sync(&priv->watchdog);
2576 del_timer_sync(&priv->monitor_recover);
2577 2571
2578 /* Station information will now be cleared in device */ 2572 /* Station information will now be cleared in device */
2579 iwl_clear_ucode_stations(priv, NULL); 2573 iwl_clear_ucode_stations(priv, NULL);
@@ -3775,12 +3769,9 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
3775 3769
3776 iwl3945_hw_setup_deferred_work(priv); 3770 iwl3945_hw_setup_deferred_work(priv);
3777 3771
3778 if (priv->cfg->ops->lib->recover_from_tx_stall) { 3772 init_timer(&priv->watchdog);
3779 init_timer(&priv->monitor_recover); 3773 priv->watchdog.data = (unsigned long)priv;
3780 priv->monitor_recover.data = (unsigned long)priv; 3774 priv->watchdog.function = iwl_bg_watchdog;
3781 priv->monitor_recover.function =
3782 priv->cfg->ops->lib->recover_from_tx_stall;
3783 }
3784 3775
3785 tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) 3776 tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
3786 iwl3945_irq_tasklet, (unsigned long)priv); 3777 iwl3945_irq_tasklet, (unsigned long)priv);