Jesse Keating 2f82dda
Back-port of the following upstream commit...
Jesse Keating 2f82dda
Jesse Keating 2f82dda
commit d4d59e88cb746165c6fe33eacb6f582d525c6ef1
Jesse Keating 2f82dda
Author: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Jesse Keating 2f82dda
Date:   Fri Jan 22 14:22:45 2010 -0800
Jesse Keating 2f82dda
Jesse Keating 2f82dda
    iwlwifi: Logic to control how frequent radio should be reset if needed
Jesse Keating 2f82dda
    
Jesse Keating 2f82dda
    Add additional logic for internal scan routine to control how
Jesse Keating 2f82dda
    frequent this function should be performed.
Jesse Keating 2f82dda
    
Jesse Keating 2f82dda
    The intent of this function is to reset/re-tune the radio and bring the
Jesse Keating 2f82dda
    RF/PHY back to normal state, it does not make sense calling it too
Jesse Keating 2f82dda
    frequent,
Jesse Keating 2f82dda
    if reset the radio can not bring it back to normal state, it indicate
Jesse Keating 2f82dda
    there are other reason to cause the radio not operate correctly.
Jesse Keating 2f82dda
    
Jesse Keating 2f82dda
    Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Jesse Keating 2f82dda
    Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Jesse Keating 2f82dda
    Signed-off-by: John W. Linville <linville@tuxdriver.com>
Jesse Keating 2f82dda
Jesse Keating 2f82dda
diff -up linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h.orig linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h
Jesse Keating 2f82dda
--- linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h.orig	2010-03-22 11:26:18.000000000 -0400
Jesse Keating 2f82dda
+++ linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h	2010-03-22 14:12:32.000000000 -0400
Jesse Keating 2f82dda
@@ -1013,6 +1013,7 @@ struct iwl_priv {
Jesse Keating 2f82dda
 	unsigned long scan_start;
Jesse Keating 2f82dda
 	unsigned long scan_pass_start;
Jesse Keating 2f82dda
 	unsigned long scan_start_tsf;
Jesse Keating 2f82dda
+	unsigned long last_internal_scan_jiffies;
Jesse Keating 2f82dda
 	void *scan;
Jesse Keating 2f82dda
 	int scan_bands;
Jesse Keating 2f82dda
 	struct cfg80211_scan_request *scan_request;
Jesse Keating 2f82dda
diff -up linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-scan.c.orig linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-scan.c
Jesse Keating 2f82dda
--- linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-scan.c.orig	2010-03-22 11:26:18.000000000 -0400
Jesse Keating 2f82dda
+++ linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-scan.c	2010-03-22 14:15:28.000000000 -0400
Jesse Keating 2f82dda
@@ -206,7 +206,8 @@ static void iwl_rx_scan_results_notif(st
Jesse Keating 2f82dda
 #endif
Jesse Keating 2f82dda
 
Jesse Keating 2f82dda
 	priv->last_scan_jiffies = jiffies;
Jesse Keating 2f82dda
-	priv->next_scan_jiffies = 0;
Jesse Keating 2f82dda
+	if (!priv->is_internal_short_scan)
Jesse Keating 2f82dda
+		priv->next_scan_jiffies = 0;
Jesse Keating 2f82dda
 }
Jesse Keating 2f82dda
 
Jesse Keating 2f82dda
 /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
Jesse Keating 2f82dda
@@ -252,8 +253,11 @@ static void iwl_rx_scan_complete_notif(s
Jesse Keating 2f82dda
 			goto reschedule;
Jesse Keating 2f82dda
 	}
Jesse Keating 2f82dda
 
Jesse Keating 2f82dda
-	priv->last_scan_jiffies = jiffies;
Jesse Keating 2f82dda
-	priv->next_scan_jiffies = 0;
Jesse Keating 2f82dda
+	if (!priv->is_internal_short_scan)
Jesse Keating 2f82dda
+		priv->next_scan_jiffies = 0;
Jesse Keating 2f82dda
+	else
Jesse Keating 2f82dda
+		priv->last_internal_scan_jiffies = jiffies;
Jesse Keating 2f82dda
+
Jesse Keating 2f82dda
 	IWL_DEBUG_INFO(priv, "Setting scan to off\n");
Jesse Keating 2f82dda
 
Jesse Keating 2f82dda
 	clear_bit(STATUS_SCANNING, &priv->status);
Jesse Keating 2f82dda
@@ -560,6 +564,8 @@ EXPORT_SYMBOL(iwl_mac_hw_scan);
Jesse Keating 2f82dda
  * internal short scan, this function should only been called while associated.
Jesse Keating 2f82dda
  * It will reset and tune the radio to prevent possible RF related problem
Jesse Keating 2f82dda
  */
Jesse Keating 2f82dda
+#define IWL_DELAY_NEXT_INTERNAL_SCAN (HZ*1)
Jesse Keating 2f82dda
+
Jesse Keating 2f82dda
 int iwl_internal_short_hw_scan(struct iwl_priv *priv)
Jesse Keating 2f82dda
 {
Jesse Keating 2f82dda
 	int ret = 0;
Jesse Keating 2f82dda
@@ -579,6 +585,13 @@ int iwl_internal_short_hw_scan(struct iw
Jesse Keating 2f82dda
 		ret = -EAGAIN;
Jesse Keating 2f82dda
 		goto out;
Jesse Keating 2f82dda
 	}
Jesse Keating 2f82dda
+	if (priv->last_internal_scan_jiffies &&
Jesse Keating 2f82dda
+	    time_after(priv->last_internal_scan_jiffies +
Jesse Keating 2f82dda
+		       IWL_DELAY_NEXT_INTERNAL_SCAN, jiffies)) {
Jesse Keating 2f82dda
+		IWL_DEBUG_SCAN(priv, "internal scan rejected\n");
Jesse Keating 2f82dda
+		goto out;
Jesse Keating 2f82dda
+	}
Jesse Keating 2f82dda
+
Jesse Keating 2f82dda
 	priv->scan_bands = 0;
Jesse Keating 2f82dda
 	if (priv->band == IEEE80211_BAND_5GHZ)
Jesse Keating 2f82dda
 		priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);