aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2010-06-21 19:52:55 -0400
committerWey-Yi Guy <wey-yi.w.guy@intel.com>2010-07-02 14:08:52 -0400
commitc04f9f220300da83f71698fa7be24714152faf0d (patch)
tree2f9a291ebcabab800e2e8070763d9d23d3197a87
parent88c1f4f6dffe66e2fed8e7e3276e091ee850bed0 (diff)
iwlwifi: fix fw_restart module parameter
fw_restart module parameter was broken by the recent check for stuck queue patch, driver check the fx_restart module parameter before reload the firmware; but the stuck queue timer kick in after firmware error and reload the firmware even fw_restart=0. In this case, driver should not reload the firmware, it is important to help debugging uCode error. The only case we can ignore the module parameter is when user request firmware reload from debugfs, which can bypass the checking and perform firmware reload all the time. Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c31
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c4
4 files changed, 27 insertions, 12 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index a56fb466d0b6..f73eb08a9494 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2627,7 +2627,7 @@ static void iwl_force_rf_reset(struct iwl_priv *priv)
2627} 2627}
2628 2628
2629 2629
2630int iwl_force_reset(struct iwl_priv *priv, int mode) 2630int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
2631{ 2631{
2632 struct iwl_force_reset *force_reset; 2632 struct iwl_force_reset *force_reset;
2633 2633
@@ -2640,12 +2640,14 @@ int iwl_force_reset(struct iwl_priv *priv, int mode)
2640 } 2640 }
2641 force_reset = &priv->force_reset[mode]; 2641 force_reset = &priv->force_reset[mode];
2642 force_reset->reset_request_count++; 2642 force_reset->reset_request_count++;
2643 if (force_reset->last_force_reset_jiffies && 2643 if (!external) {
2644 time_after(force_reset->last_force_reset_jiffies + 2644 if (force_reset->last_force_reset_jiffies &&
2645 force_reset->reset_duration, jiffies)) { 2645 time_after(force_reset->last_force_reset_jiffies +
2646 IWL_DEBUG_INFO(priv, "force reset rejected\n"); 2646 force_reset->reset_duration, jiffies)) {
2647 force_reset->reset_reject_count++; 2647 IWL_DEBUG_INFO(priv, "force reset rejected\n");
2648 return -EAGAIN; 2648 force_reset->reset_reject_count++;
2649 return -EAGAIN;
2650 }
2649 } 2651 }
2650 force_reset->reset_success_count++; 2652 force_reset->reset_success_count++;
2651 force_reset->last_force_reset_jiffies = jiffies; 2653 force_reset->last_force_reset_jiffies = jiffies;
@@ -2655,6 +2657,19 @@ int iwl_force_reset(struct iwl_priv *priv, int mode)
2655 iwl_force_rf_reset(priv); 2657 iwl_force_rf_reset(priv);
2656 break; 2658 break;
2657 case IWL_FW_RESET: 2659 case IWL_FW_RESET:
2660 /*
2661 * if the request is from external(ex: debugfs),
2662 * then always perform the request in regardless the module
2663 * parameter setting
2664 * if the request is from internal (uCode error or driver
2665 * detect failure), then fw_restart module parameter
2666 * need to be check before performing firmware reload
2667 */
2668 if (!external && !priv->cfg->mod_params->restart_fw) {
2669 IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
2670 "module parameter setting\n");
2671 break;
2672 }
2658 IWL_ERR(priv, "On demand firmware reload\n"); 2673 IWL_ERR(priv, "On demand firmware reload\n");
2659 /* Set the FW error flag -- cleared on iwl_down */ 2674 /* Set the FW error flag -- cleared on iwl_down */
2660 set_bit(STATUS_FW_ERROR, &priv->status); 2675 set_bit(STATUS_FW_ERROR, &priv->status);
@@ -2713,7 +2728,7 @@ static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt)
2713 "queue %d stuck %d time. Fw reload.\n", 2728 "queue %d stuck %d time. Fw reload.\n",
2714 q->id, q->repeat_same_read_ptr); 2729 q->id, q->repeat_same_read_ptr);
2715 q->repeat_same_read_ptr = 0; 2730 q->repeat_same_read_ptr = 0;
2716 iwl_force_reset(priv, IWL_FW_RESET); 2731 iwl_force_reset(priv, IWL_FW_RESET, false);
2717 } else { 2732 } else {
2718 q->repeat_same_read_ptr++; 2733 q->repeat_same_read_ptr++;
2719 IWL_DEBUG_RADIO(priv, 2734 IWL_DEBUG_RADIO(priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 15930e064022..bfa34561d9da 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -525,7 +525,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
525 struct cfg80211_scan_request *req); 525 struct cfg80211_scan_request *req);
526void iwl_bg_start_internal_scan(struct work_struct *work); 526void iwl_bg_start_internal_scan(struct work_struct *work);
527void iwl_internal_short_hw_scan(struct iwl_priv *priv); 527void iwl_internal_short_hw_scan(struct iwl_priv *priv);
528int iwl_force_reset(struct iwl_priv *priv, int mode); 528int iwl_force_reset(struct iwl_priv *priv, int mode, bool external);
529u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, 529u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
530 const u8 *ta, const u8 *ie, int ie_len, int left); 530 const u8 *ta, const u8 *ie, int ie_len, int left);
531void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); 531void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 7d9ffc1575de..48f890883f4e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -1487,7 +1487,7 @@ static ssize_t iwl_dbgfs_force_reset_write(struct file *file,
1487 switch (reset) { 1487 switch (reset) {
1488 case IWL_RF_RESET: 1488 case IWL_RF_RESET:
1489 case IWL_FW_RESET: 1489 case IWL_FW_RESET:
1490 ret = iwl_force_reset(priv, reset); 1490 ret = iwl_force_reset(priv, reset, true);
1491 break; 1491 break;
1492 default: 1492 default:
1493 return -EINVAL; 1493 return -EINVAL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index b437f317b979..79773e353baa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -238,7 +238,7 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
238 */ 238 */
239 IWL_ERR(priv, "low ack count detected, " 239 IWL_ERR(priv, "low ack count detected, "
240 "restart firmware\n"); 240 "restart firmware\n");
241 if (!iwl_force_reset(priv, IWL_FW_RESET)) 241 if (!iwl_force_reset(priv, IWL_FW_RESET, false))
242 return; 242 return;
243 } 243 }
244 } 244 }
@@ -249,7 +249,7 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
249 * high plcp error detected 249 * high plcp error detected
250 * reset Radio 250 * reset Radio
251 */ 251 */
252 iwl_force_reset(priv, IWL_RF_RESET); 252 iwl_force_reset(priv, IWL_RF_RESET, false);
253 } 253 }
254 } 254 }
255 } 255 }