173 lines
6.5 KiB
Diff
173 lines
6.5 KiB
Diff
Backport of the following upstream commit...
|
|
|
|
commit a93e7973d0983d22fcbe5f691244736211639fe7
|
|
Author: Wey-Yi Guy <wey-yi.w.guy@intel.com>
|
|
Date: Wed Feb 3 11:47:19 2010 -0800
|
|
|
|
iwlwifi: multiple force reset mode
|
|
|
|
Provide the function to perform different type of uCode reset/reload operation.
|
|
When uCode detect error and can not fix itself, this iwl_force_reset()
|
|
function allow driver to perform the necessary reset/reload functions and help
|
|
to bring uCode back to normal operation state.
|
|
|
|
Currently only 2 type of force reset are available:
|
|
- reset radio
|
|
- reload firmware
|
|
|
|
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
|
|
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
|
|
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-core.c.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-core.c
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-core.c.orig 2010-04-13 13:36:35.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-core.c 2010-04-13 13:38:40.000000000 -0400
|
|
@@ -3197,7 +3197,7 @@ void iwl_update_stats(struct iwl_priv *p
|
|
EXPORT_SYMBOL(iwl_update_stats);
|
|
#endif
|
|
|
|
-void iwl_force_rf_reset(struct iwl_priv *priv)
|
|
+static void iwl_force_rf_reset(struct iwl_priv *priv)
|
|
{
|
|
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
|
return;
|
|
@@ -3219,7 +3219,47 @@ void iwl_force_rf_reset(struct iwl_priv
|
|
iwl_internal_short_hw_scan(priv);
|
|
return;
|
|
}
|
|
-EXPORT_SYMBOL(iwl_force_rf_reset);
|
|
+
|
|
+#define IWL_DELAY_NEXT_FORCE_RESET (HZ*3)
|
|
+
|
|
+int iwl_force_reset(struct iwl_priv *priv, int mode)
|
|
+{
|
|
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (priv->last_force_reset_jiffies &&
|
|
+ time_after(priv->last_force_reset_jiffies +
|
|
+ IWL_DELAY_NEXT_FORCE_RESET, jiffies)) {
|
|
+ IWL_DEBUG_INFO(priv, "force reset rejected\n");
|
|
+ return -EAGAIN;
|
|
+ }
|
|
+
|
|
+ IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
|
|
+
|
|
+ switch (mode) {
|
|
+ case IWL_RF_RESET:
|
|
+ iwl_force_rf_reset(priv);
|
|
+ break;
|
|
+ case IWL_FW_RESET:
|
|
+ IWL_ERR(priv, "On demand firmware reload\n");
|
|
+ /* Set the FW error flag -- cleared on iwl_down */
|
|
+ set_bit(STATUS_FW_ERROR, &priv->status);
|
|
+ wake_up_interruptible(&priv->wait_command_queue);
|
|
+ /*
|
|
+ * Keep the restart process from trying to send host
|
|
+ * commands by clearing the INIT status bit
|
|
+ */
|
|
+ clear_bit(STATUS_READY, &priv->status);
|
|
+ queue_work(priv->workqueue, &priv->restart);
|
|
+ break;
|
|
+ default:
|
|
+ IWL_DEBUG_INFO(priv, "invalid reset request.\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ priv->last_force_reset_jiffies = jiffies;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
|
|
#ifdef CONFIG_PM
|
|
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-core.h.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-core.h
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-core.h.orig 2010-04-13 13:36:50.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-core.h 2010-04-13 13:38:40.000000000 -0400
|
|
@@ -501,7 +501,7 @@ int iwl_scan_cancel(struct iwl_priv *pri
|
|
int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
|
|
int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
|
|
int iwl_internal_short_hw_scan(struct iwl_priv *priv);
|
|
-void iwl_force_rf_reset(struct iwl_priv *priv);
|
|
+int iwl_force_reset(struct iwl_priv *priv, int mode);
|
|
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
|
|
const u8 *ie, int ie_len, int left);
|
|
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h.orig 2010-04-13 13:36:50.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h 2010-04-13 13:38:40.000000000 -0400
|
|
@@ -993,6 +993,11 @@ struct iwl_switch_rxon {
|
|
#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100)
|
|
#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)
|
|
|
|
+enum iwl_reset {
|
|
+ IWL_RF_RESET = 0,
|
|
+ IWL_FW_RESET,
|
|
+};
|
|
+
|
|
struct iwl_priv {
|
|
|
|
/* ieee device used by generic ieee processing code */
|
|
@@ -1024,6 +1029,9 @@ struct iwl_priv {
|
|
/* storing the jiffies when the plcp error rate is received */
|
|
unsigned long plcp_jiffies;
|
|
|
|
+ /* force reset */
|
|
+ unsigned long last_force_reset_jiffies;
|
|
+
|
|
/* we allocate array of iwl4965_channel_info for NIC's valid channels.
|
|
* Access via channel # using indirect index array */
|
|
struct iwl_channel_info *channel_info; /* channel info array */
|
|
@@ -1046,7 +1054,6 @@ struct iwl_priv {
|
|
unsigned long scan_start;
|
|
unsigned long scan_pass_start;
|
|
unsigned long scan_start_tsf;
|
|
- unsigned long last_internal_scan_jiffies;
|
|
void *scan;
|
|
int scan_bands;
|
|
struct cfg80211_scan_request *scan_request;
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c.orig 2010-04-13 13:36:50.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c 2010-04-13 13:38:40.000000000 -0400
|
|
@@ -662,7 +662,7 @@ void iwl_rx_statistics(struct iwl_priv *
|
|
* Reset the RF radio due to the high plcp
|
|
* error rate
|
|
*/
|
|
- iwl_force_rf_reset(priv);
|
|
+ iwl_force_reset(priv, IWL_RF_RESET);
|
|
}
|
|
}
|
|
|
|
diff -up linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-scan.c.orig linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-scan.c
|
|
--- linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-scan.c.orig 2010-04-13 13:36:42.000000000 -0400
|
|
+++ linux-2.6.33.noarch/drivers/net/wireless/iwlwifi/iwl-scan.c 2010-04-13 13:38:40.000000000 -0400
|
|
@@ -254,8 +254,6 @@ static void iwl_rx_scan_complete_notif(s
|
|
priv->last_scan_jiffies = jiffies;
|
|
if (!priv->is_internal_short_scan)
|
|
priv->next_scan_jiffies = 0;
|
|
- else
|
|
- priv->last_internal_scan_jiffies = jiffies;
|
|
|
|
IWL_DEBUG_INFO(priv, "Setting scan to off\n");
|
|
|
|
@@ -564,8 +562,6 @@ EXPORT_SYMBOL(iwl_mac_hw_scan);
|
|
* internal short scan, this function should only been called while associated.
|
|
* It will reset and tune the radio to prevent possible RF related problem
|
|
*/
|
|
-#define IWL_DELAY_NEXT_INTERNAL_SCAN (HZ*1)
|
|
-
|
|
int iwl_internal_short_hw_scan(struct iwl_priv *priv)
|
|
{
|
|
int ret = 0;
|
|
@@ -585,12 +581,6 @@ int iwl_internal_short_hw_scan(struct iw
|
|
ret = -EAGAIN;
|
|
goto out;
|
|
}
|
|
- if (priv->last_internal_scan_jiffies &&
|
|
- time_after(priv->last_internal_scan_jiffies +
|
|
- IWL_DELAY_NEXT_INTERNAL_SCAN, jiffies)) {
|
|
- IWL_DEBUG_SCAN(priv, "internal scan rejected\n");
|
|
- goto out;
|
|
- }
|
|
|
|
priv->scan_bands = 0;
|
|
if (priv->band == IEEE80211_BAND_5GHZ)
|