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