iwlwifi: do proper hw restart
authorJohannes Berg <johannes@sipsolutions.net>
Fri, 8 May 2009 20:44:36 +0000 (13:44 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 11 May 2009 19:23:57 +0000 (15:23 -0400)
When the microcode fails for any reason, ask mac80211 to
recover instead of trying ourselves and failing at it.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl3945-base.c

index 6cdee0b4b486acecba1b2113aa73e858146f32c2..43bc8a66864e52165fe8be1755daa5b98143c381 100644 (file)
@@ -190,8 +190,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
 
        priv->cfg->ops->smgmt->clear_station_table(priv);
 
-       if (!priv->error_recovering)
-               priv->start_calib = 0;
+       priv->start_calib = 0;
 
        /* Add the broadcast address so we can send broadcast frames */
        if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
@@ -967,23 +966,6 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv)
        tasklet_kill(&priv->irq_tasklet);
 }
 
-static void iwl_error_recovery(struct iwl_priv *priv)
-{
-       unsigned long flags;
-
-       memcpy(&priv->staging_rxon, &priv->recovery_rxon,
-              sizeof(priv->staging_rxon));
-       priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-       iwlcore_commit_rxon(priv);
-
-       iwl_rxon_add_station(priv, priv->bssid, 1);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
-       priv->error_recovering = 0;
-       spin_unlock_irqrestore(&priv->lock, flags);
-}
-
 static void iwl_irq_tasklet(struct iwl_priv *priv)
 {
        u32 inta, handled = 0;
@@ -1514,9 +1496,6 @@ static void iwl_alive_start(struct iwl_priv *priv)
        set_bit(STATUS_READY, &priv->status);
        wake_up_interruptible(&priv->wait_command_queue);
 
-       if (priv->error_recovering)
-               iwl_error_recovery(priv);
-
        iwl_power_update_mode(priv, 1);
 
        /* reassociate for ADHOC mode */
@@ -1715,9 +1694,6 @@ static int __iwl_up(struct iwl_priv *priv)
                        continue;
                }
 
-               /* Clear out the uCode error bit if it is set */
-               clear_bit(STATUS_FW_ERROR, &priv->status);
-
                /* start card; "initialize" will load runtime ucode */
                iwl_nic_start(priv);
 
@@ -1812,8 +1788,17 @@ static void iwl_bg_restart(struct work_struct *data)
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       iwl_down(priv);
-       queue_work(priv->workqueue, &priv->up);
+       if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+               mutex_lock(&priv->mutex);
+               priv->vif = NULL;
+               priv->is_open = 0;
+               mutex_unlock(&priv->mutex);
+               iwl_down(priv);
+               ieee80211_restart_hw(priv->hw);
+       } else {
+               iwl_down(priv);
+               queue_work(priv->workqueue, &priv->up);
+       }
 }
 
 static void iwl_bg_rx_replenish(struct work_struct *data)
@@ -2007,10 +1992,8 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
 
        IWL_DEBUG_MAC80211(priv, "enter\n");
 
-       if (!priv->is_open) {
-               IWL_DEBUG_MAC80211(priv, "leave - skip\n");
+       if (!priv->is_open)
                return;
-       }
 
        priv->is_open = 0;
 
index a9a4fcef7e42007ffa375f1a7a36995941b7c7cd..aa1e1dc95ef6cdb8f3fef85633890dddecdf393e 100644 (file)
@@ -1229,11 +1229,6 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
                IWL_DEBUG(priv, IWL_DL_FW_ERRORS,
                          "Restarting adapter due to uCode error.\n");
 
-               if (iwl_is_associated(priv)) {
-                       memcpy(&priv->recovery_rxon, &priv->active_rxon,
-                              sizeof(priv->recovery_rxon));
-                       priv->error_recovering = 1;
-               }
                if (priv->cfg->mod_params->restart_fw)
                        queue_work(priv->workqueue, &priv->restart);
        }
index 5aa76a7063209018742fc740ed8fff6d7b82fd0f..0f2c1b2175150ef51ea412964b8c2a74fef81ad4 100644 (file)
@@ -933,7 +933,6 @@ struct iwl_priv {
        const struct iwl_rxon_cmd active_rxon;
        struct iwl_rxon_cmd staging_rxon;
 
-       int error_recovering;
        struct iwl_rxon_cmd recovery_rxon;
 
        /* 1st responses from initialize and runtime uCode images.
index f6c1489a0c4aa5dc4f388dd4af6fbb0b5e8f8947..271e5d1f8425e50b291cf9ca87f9e162b770d00e 100644 (file)
@@ -1837,23 +1837,6 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
        iwl_release_nic_access(priv);
 }
 
-static void iwl3945_error_recovery(struct iwl_priv *priv)
-{
-       unsigned long flags;
-
-       memcpy(&priv->staging_rxon, &priv->recovery_rxon,
-              sizeof(priv->staging_rxon));
-       priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-       iwlcore_commit_rxon(priv);
-
-       priv->cfg->ops->smgmt->add_station(priv, priv->bssid, 1, 0, NULL);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
-       priv->error_recovering = 0;
-       spin_unlock_irqrestore(&priv->lock, flags);
-}
-
 static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 {
        u32 inta, handled = 0;
@@ -2683,9 +2666,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
        /* After the ALIVE response, we can send commands to 3945 uCode */
        set_bit(STATUS_ALIVE, &priv->status);
 
-       /* Clear out the uCode error bit if it is set */
-       clear_bit(STATUS_FW_ERROR, &priv->status);
-
        if (iwl_is_rfkill(priv))
                return;
 
@@ -2722,9 +2702,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
        set_bit(STATUS_READY, &priv->status);
        wake_up_interruptible(&priv->wait_command_queue);
 
-       if (priv->error_recovering)
-               iwl3945_error_recovery(priv);
-
        /* reassociate for ADHOC mode */
        if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
                struct sk_buff *beacon = ieee80211_beacon_get(priv->hw,
@@ -3231,8 +3208,17 @@ static void iwl3945_bg_restart(struct work_struct *data)
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       iwl3945_down(priv);
-       queue_work(priv->workqueue, &priv->up);
+       if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+               mutex_lock(&priv->mutex);
+               priv->vif = NULL;
+               priv->is_open = 0;
+               mutex_unlock(&priv->mutex);
+               iwl3945_down(priv);
+               ieee80211_restart_hw(priv->hw);
+       } else {
+               iwl3945_down(priv);
+               queue_work(priv->workqueue, &priv->up);
+       }
 }
 
 static void iwl3945_bg_rx_replenish(struct work_struct *data)