iwlwifi: Limit number of firmware reload
authorWey-Yi Guy <wey-yi.w.guy@intel.com>
Wed, 9 Feb 2011 17:37:46 +0000 (09:37 -0800)
committerWey-Yi Guy <wey-yi.w.guy@intel.com>
Mon, 21 Feb 2011 18:08:15 +0000 (10:08 -0800)
If device has serious problem and cause firmware can not recover itself.
Keep reloading firmware will not help, it can only fill up the syslog and
lock up the system because busy reloading.

Introduce the limit reload counter, if the reload reach the maximum within
the pre-defined duration;stop the reload operation.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-dev.h

index 4ad89389a0a974f5cfb50bd77ce51c3dd10bdb24..977ddfb8c24c32b82321e5a5b2eed536c33eb370 100644 (file)
@@ -948,6 +948,9 @@ EXPORT_SYMBOL(iwl_print_rx_config_cmd);
  */
 void iwl_irq_handle_error(struct iwl_priv *priv)
 {
+       unsigned int reload_msec;
+       unsigned long reload_jiffies;
+
        /* Set the FW error flag -- cleared on iwl_down */
        set_bit(STATUS_FW_ERROR, &priv->status);
 
@@ -991,6 +994,25 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
         * commands by clearing the INIT status bit */
        clear_bit(STATUS_READY, &priv->status);
 
+       /*
+        * If firmware keep reloading, then it indicate something
+        * serious wrong and firmware having problem to recover
+        * from it. Instead of keep trying which will fill the syslog
+        * and hang the system, let's just stop it
+        */
+       reload_jiffies = jiffies;
+       reload_msec = jiffies_to_msecs((long) reload_jiffies -
+                               (long) priv->reload_jiffies);
+       priv->reload_jiffies = reload_jiffies;
+       if (reload_msec <= IWL_MIN_RELOAD_DURATION) {
+               priv->reload_count++;
+               if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) {
+                       IWL_ERR(priv, "BUG_ON, Stop restarting\n");
+                       return;
+               }
+       } else
+               priv->reload_count = 0;
+
        if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
                IWL_DEBUG(priv, IWL_DL_FW_ERRORS,
                          "Restarting adapter due to uCode error.\n");
index ecfbef402781ddbbd01a5b8d39d58394f374e765..065615ee040aed7066fcd66102602f67c5dc8773 100644 (file)
@@ -1110,6 +1110,11 @@ struct iwl_event_log {
 /* BT Antenna Coupling Threshold (dB) */
 #define IWL_BT_ANTENNA_COUPLING_THRESHOLD      (35)
 
+/* Firmware reload counter and Timestamp */
+#define IWL_MIN_RELOAD_DURATION                1000 /* 1000 ms */
+#define IWL_MAX_CONTINUE_RELOAD_CNT    4
+
+
 enum iwl_reset {
        IWL_RF_RESET = 0,
        IWL_FW_RESET,
@@ -1262,6 +1267,10 @@ struct iwl_priv {
        /* force reset */
        struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
 
+       /* firmware reload counter and timestamp */
+       unsigned long reload_jiffies;
+       int reload_count;
+
        /* we allocate array of iwl_channel_info for NIC's valid channels.
         *    Access via channel # using indirect index array */
        struct iwl_channel_info *channel_info;  /* channel info array */