]> git.karo-electronics.de Git - linux-beck.git/commitdiff
iwlwifi: fix fw_restart module parameter
authorWey-Yi Guy <wey-yi.w.guy@intel.com>
Mon, 21 Jun 2010 23:52:55 +0000 (16:52 -0700)
committerWey-Yi Guy <wey-yi.w.guy@intel.com>
Fri, 2 Jul 2010 18:08:52 +0000 (11:08 -0700)
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>
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-debugfs.c
drivers/net/wireless/iwlwifi/iwl-rx.c

index a56fb466d0b6437d69de229c85724b74a4e5f507..f73eb08a949450959bd2d403346781af6fe28ff0 100644 (file)
@@ -2627,7 +2627,7 @@ static void iwl_force_rf_reset(struct iwl_priv *priv)
 }
 
 
-int iwl_force_reset(struct iwl_priv *priv, int mode)
+int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
 {
        struct iwl_force_reset *force_reset;
 
@@ -2640,12 +2640,14 @@ int iwl_force_reset(struct iwl_priv *priv, int mode)
        }
        force_reset = &priv->force_reset[mode];
        force_reset->reset_request_count++;
-       if (force_reset->last_force_reset_jiffies &&
-           time_after(force_reset->last_force_reset_jiffies +
-           force_reset->reset_duration, jiffies)) {
-               IWL_DEBUG_INFO(priv, "force reset rejected\n");
-               force_reset->reset_reject_count++;
-               return -EAGAIN;
+       if (!external) {
+               if (force_reset->last_force_reset_jiffies &&
+                   time_after(force_reset->last_force_reset_jiffies +
+                   force_reset->reset_duration, jiffies)) {
+                       IWL_DEBUG_INFO(priv, "force reset rejected\n");
+                       force_reset->reset_reject_count++;
+                       return -EAGAIN;
+               }
        }
        force_reset->reset_success_count++;
        force_reset->last_force_reset_jiffies = jiffies;
@@ -2655,6 +2657,19 @@ int iwl_force_reset(struct iwl_priv *priv, int mode)
                iwl_force_rf_reset(priv);
                break;
        case IWL_FW_RESET:
+               /*
+                * if the request is from external(ex: debugfs),
+                * then always perform the request in regardless the module
+                * parameter setting
+                * if the request is from internal (uCode error or driver
+                * detect failure), then fw_restart module parameter
+                * need to be check before performing firmware reload
+                */
+               if (!external && !priv->cfg->mod_params->restart_fw) {
+                       IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
+                                      "module parameter setting\n");
+                       break;
+               }
                IWL_ERR(priv, "On demand firmware reload\n");
                /* Set the FW error flag -- cleared on iwl_down */
                set_bit(STATUS_FW_ERROR, &priv->status);
@@ -2713,7 +2728,7 @@ static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt)
                                        "queue %d stuck %d time. Fw reload.\n",
                                        q->id, q->repeat_same_read_ptr);
                                q->repeat_same_read_ptr = 0;
-                               iwl_force_reset(priv, IWL_FW_RESET);
+                               iwl_force_reset(priv, IWL_FW_RESET, false);
                        } else {
                                q->repeat_same_read_ptr++;
                                IWL_DEBUG_RADIO(priv,
index 15930e06402247b8ff360ccab61b76e254b1353b..bfa34561d9da51ef1d07993794c1231ac2667def 100644 (file)
@@ -525,7 +525,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
                    struct cfg80211_scan_request *req);
 void iwl_bg_start_internal_scan(struct work_struct *work);
 void iwl_internal_short_hw_scan(struct iwl_priv *priv);
-int iwl_force_reset(struct iwl_priv *priv, int mode);
+int iwl_force_reset(struct iwl_priv *priv, int mode, bool external);
 u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
                       const u8 *ta, const u8 *ie, int ie_len, int left);
 void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
index 7d9ffc1575de761531f3f1610edfa135e54eb468..48f890883f4e42bf40362a7d40e6383ffec28118 100644 (file)
@@ -1487,7 +1487,7 @@ static ssize_t iwl_dbgfs_force_reset_write(struct file *file,
        switch (reset) {
        case IWL_RF_RESET:
        case IWL_FW_RESET:
-               ret = iwl_force_reset(priv, reset);
+               ret = iwl_force_reset(priv, reset, true);
                break;
        default:
                return -EINVAL;
index b437f317b979066576f2482dd4a58e3cfb2f2425..79773e353baaa56478a6d173fdc5f0f70cf837fa 100644 (file)
@@ -238,7 +238,7 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
                                 */
                                IWL_ERR(priv, "low ack count detected, "
                                        "restart firmware\n");
-                               if (!iwl_force_reset(priv, IWL_FW_RESET))
+                               if (!iwl_force_reset(priv, IWL_FW_RESET, false))
                                        return;
                        }
                }
@@ -249,7 +249,7 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
                                 * high plcp error detected
                                 * reset Radio
                                 */
-                               iwl_force_reset(priv, IWL_RF_RESET);
+                               iwl_force_reset(priv, IWL_RF_RESET, false);
                        }
                }
        }