kernel/iwlwifi_-multiple-force-res...

153 lines
5.8 KiB
Diff

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
--- linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-core.c.orig 2010-03-22 16:37:23.000000000 -0400
+++ linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-core.c 2010-03-22 16:39:46.000000000 -0400
@@ -3035,7 +3035,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;
@@ -3057,7 +3057,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.32.noarch/drivers/net/wireless/iwlwifi/iwl-core.h.orig linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-core.h
--- linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-core.h.orig 2010-03-22 16:37:23.000000000 -0400
+++ linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-core.h 2010-03-22 16:39:46.000000000 -0400
@@ -465,7 +465,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.32.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h.orig linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h
--- linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h.orig 2010-03-22 16:37:23.000000000 -0400
+++ linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h 2010-03-22 16:39:46.000000000 -0400
@@ -972,6 +972,11 @@ struct traffic_stats {
#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 */
@@ -1003,6 +1008,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 */
@@ -1025,7 +1033,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.32.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c.orig linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c
--- linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c.orig 2010-03-22 16:37:23.000000000 -0400
+++ linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-rx.c 2010-03-22 16:39:46.000000000 -0400
@@ -616,7 +616,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.32.noarch/drivers/net/wireless/iwlwifi/iwl-scan.c.orig linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-scan.c
--- linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-scan.c.orig 2010-03-22 16:37:23.000000000 -0400
+++ linux-2.6.32.noarch/drivers/net/wireless/iwlwifi/iwl-scan.c 2010-03-22 16:39:46.000000000 -0400
@@ -255,8 +255,6 @@ static void iwl_rx_scan_complete_notif(s
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)