Jesse Keating 2f82dda
diff -up linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-core.c.orig linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-core.c
Jesse Keating 2f82dda
--- linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-core.c.orig	2010-03-22 16:37:23.000000000 -0400
Jesse Keating 2f82dda
+++ linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-core.c	2010-03-22 16:39:46.000000000 -0400
Jesse Keating 2f82dda
@@ -3035,7 +3035,7 @@ void iwl_update_stats(struct iwl_priv *p
Jesse Keating 2f82dda
 EXPORT_SYMBOL(iwl_update_stats);
Jesse Keating 2f82dda
 #endif
Jesse Keating 2f82dda
 
Jesse Keating 2f82dda
-void iwl_force_rf_reset(struct iwl_priv *priv)
Jesse Keating 2f82dda
+static void iwl_force_rf_reset(struct iwl_priv *priv)
Jesse Keating 2f82dda
 {
Jesse Keating 2f82dda
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
Jesse Keating 2f82dda
 		return;
Jesse Keating 2f82dda
@@ -3057,7 +3057,47 @@ void iwl_force_rf_reset(struct iwl_priv 
Jesse Keating 2f82dda
 	iwl_internal_short_hw_scan(priv);
Jesse Keating 2f82dda
 	return;
Jesse Keating 2f82dda
 }
Jesse Keating 2f82dda
-EXPORT_SYMBOL(iwl_force_rf_reset);
Jesse Keating 2f82dda
+
Jesse Keating 2f82dda
+#define IWL_DELAY_NEXT_FORCE_RESET (HZ*3)
Jesse Keating 2f82dda
+
Jesse Keating 2f82dda
+int iwl_force_reset(struct iwl_priv *priv, int mode)
Jesse Keating 2f82dda
+{
Jesse Keating 2f82dda
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
Jesse Keating 2f82dda
+		return -EINVAL;
Jesse Keating 2f82dda
+
Jesse Keating 2f82dda
+	if (priv->last_force_reset_jiffies &&
Jesse Keating 2f82dda
+	    time_after(priv->last_force_reset_jiffies +
Jesse Keating 2f82dda
+		       IWL_DELAY_NEXT_FORCE_RESET, jiffies)) {
Jesse Keating 2f82dda
+		IWL_DEBUG_INFO(priv, "force reset rejected\n");
Jesse Keating 2f82dda
+		return -EAGAIN;
Jesse Keating 2f82dda
+	}
Jesse Keating 2f82dda
+
Jesse Keating 2f82dda
+	IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
Jesse Keating 2f82dda
+
Jesse Keating 2f82dda
+	switch (mode) {
Jesse Keating 2f82dda
+	case IWL_RF_RESET:
Jesse Keating 2f82dda
+		iwl_force_rf_reset(priv);
Jesse Keating 2f82dda
+		break;
Jesse Keating 2f82dda
+	case IWL_FW_RESET:
Jesse Keating 2f82dda
+		IWL_ERR(priv, "On demand firmware reload\n");
Jesse Keating 2f82dda
+		/* Set the FW error flag -- cleared on iwl_down */
Jesse Keating 2f82dda
+		set_bit(STATUS_FW_ERROR, &priv->status);
Jesse Keating 2f82dda
+		wake_up_interruptible(&priv->wait_command_queue);
Jesse Keating 2f82dda
+		/*
Jesse Keating 2f82dda
+		 * Keep the restart process from trying to send host
Jesse Keating 2f82dda
+		 * commands by clearing the INIT status bit
Jesse Keating 2f82dda
+		 */
Jesse Keating 2f82dda
+		clear_bit(STATUS_READY, &priv->status);
Jesse Keating 2f82dda
+		queue_work(priv->workqueue, &priv->restart);
Jesse Keating 2f82dda
+		break;
Jesse Keating 2f82dda
+	default:
Jesse Keating 2f82dda
+		IWL_DEBUG_INFO(priv, "invalid reset request.\n");
Jesse Keating 2f82dda
+		return -EINVAL;
Jesse Keating 2f82dda
+	}
Jesse Keating 2f82dda
+	priv->last_force_reset_jiffies = jiffies;
Jesse Keating 2f82dda
+
Jesse Keating 2f82dda
+	return 0;
Jesse Keating 2f82dda
+}
Jesse Keating 2f82dda
 
Jesse Keating 2f82dda
 #ifdef CONFIG_PM
Jesse Keating 2f82dda
 
Jesse Keating 2f82dda
diff -up linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-core.h.orig linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-core.h
Jesse Keating 2f82dda
--- linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-core.h.orig	2010-03-22 16:37:23.000000000 -0400
Jesse Keating 2f82dda
+++ linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-core.h	2010-03-22 16:39:46.000000000 -0400
Jesse Keating 2f82dda
@@ -465,7 +465,7 @@ int iwl_scan_cancel(struct iwl_priv *pri
Jesse Keating 2f82dda
 int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
Jesse Keating 2f82dda
 int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
Jesse Keating 2f82dda
 int iwl_internal_short_hw_scan(struct iwl_priv *priv);
Jesse Keating 2f82dda
-void iwl_force_rf_reset(struct iwl_priv *priv);
Jesse Keating 2f82dda
+int iwl_force_reset(struct iwl_priv *priv, int mode);
Jesse Keating 2f82dda
 u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
Jesse Keating 2f82dda
 		       const u8 *ie, int ie_len, int left);
Jesse Keating 2f82dda
 void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
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 16:37:23.000000000 -0400
Jesse Keating 2f82dda
+++ linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h	2010-03-22 16:39:46.000000000 -0400
Jesse Keating 2f82dda
@@ -972,6 +972,11 @@ struct traffic_stats {
Jesse Keating 2f82dda
 #define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF	(100)
Jesse Keating 2f82dda
 #define IWL_MAX_PLCP_ERR_THRESHOLD_MAX	(255)
Jesse Keating 2f82dda
 
Jesse Keating 2f82dda
+enum iwl_reset {
Jesse Keating 2f82dda
+	IWL_RF_RESET = 0,
Jesse Keating 2f82dda
+	IWL_FW_RESET,
Jesse Keating 2f82dda
+};
Jesse Keating 2f82dda
+
Jesse Keating 2f82dda
 struct iwl_priv {
Jesse Keating 2f82dda
 
Jesse Keating 2f82dda
 	/* ieee device used by generic ieee processing code */
Jesse Keating 2f82dda
@@ -1003,6 +1008,9 @@ struct iwl_priv {
Jesse Keating 2f82dda
 	/* storing the jiffies when the plcp error rate is received */
Jesse Keating 2f82dda
 	unsigned long plcp_jiffies;
Jesse Keating 2f82dda
 
Jesse Keating 2f82dda
+	/* force reset */
Jesse Keating 2f82dda
+	unsigned long last_force_reset_jiffies;
Jesse Keating 2f82dda
+
Jesse Keating 2f82dda
 	/* we allocate array of iwl4965_channel_info for NIC's valid channels.
Jesse Keating 2f82dda
 	 *    Access via channel # using indirect index array */
Jesse Keating 2f82dda
 	struct iwl_channel_info *channel_info;	/* channel info array */
Jesse Keating 2f82dda
@@ -1025,7 +1033,6 @@ 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-rx.c.orig linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c
Jesse Keating 2f82dda
--- linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c.orig	2010-03-22 16:37:23.000000000 -0400
Jesse Keating 2f82dda
+++ linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c	2010-03-22 16:39:46.000000000 -0400
Jesse Keating 2f82dda
@@ -616,7 +616,7 @@ void iwl_rx_statistics(struct iwl_priv *
Jesse Keating 2f82dda
 			 * Reset the RF radio due to the high plcp
Jesse Keating 2f82dda
 			 * error rate
Jesse Keating 2f82dda
 			 */
Jesse Keating 2f82dda
-			iwl_force_rf_reset(priv);
Jesse Keating 2f82dda
+			iwl_force_reset(priv, IWL_RF_RESET);
Jesse Keating 2f82dda
 		}
Jesse Keating 2f82dda
 	}
Jesse Keating 2f82dda
 
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 16:37:23.000000000 -0400
Jesse Keating 2f82dda
+++ linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-scan.c	2010-03-22 16:39:46.000000000 -0400
Jesse Keating 2f82dda
@@ -255,8 +255,6 @@ static void iwl_rx_scan_complete_notif(s
Jesse Keating 2f82dda
 
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
@@ -564,8 +562,6 @@ 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
@@ -585,12 +581,6 @@ 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)