aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-05-08 16:44:36 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-11 15:23:57 -0400
commit19cc10870ece942d287241937944c237130f50f4 (patch)
treebda1c1eb5750159c3470ca66607e7050dfc8d49c /drivers
parent44033f80cefd1d7b474efdabc412476d4bafb8f4 (diff)
iwlwifi: do proper hw restart
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c43
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c36
4 files changed, 24 insertions, 61 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 6cdee0b4b486..43bc8a66864e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -190,8 +190,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
190 190
191 priv->cfg->ops->smgmt->clear_station_table(priv); 191 priv->cfg->ops->smgmt->clear_station_table(priv);
192 192
193 if (!priv->error_recovering) 193 priv->start_calib = 0;
194 priv->start_calib = 0;
195 194
196 /* Add the broadcast address so we can send broadcast frames */ 195 /* Add the broadcast address so we can send broadcast frames */
197 if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == 196 if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
@@ -967,23 +966,6 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv)
967 tasklet_kill(&priv->irq_tasklet); 966 tasklet_kill(&priv->irq_tasklet);
968} 967}
969 968
970static void iwl_error_recovery(struct iwl_priv *priv)
971{
972 unsigned long flags;
973
974 memcpy(&priv->staging_rxon, &priv->recovery_rxon,
975 sizeof(priv->staging_rxon));
976 priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
977 iwlcore_commit_rxon(priv);
978
979 iwl_rxon_add_station(priv, priv->bssid, 1);
980
981 spin_lock_irqsave(&priv->lock, flags);
982 priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
983 priv->error_recovering = 0;
984 spin_unlock_irqrestore(&priv->lock, flags);
985}
986
987static void iwl_irq_tasklet(struct iwl_priv *priv) 969static void iwl_irq_tasklet(struct iwl_priv *priv)
988{ 970{
989 u32 inta, handled = 0; 971 u32 inta, handled = 0;
@@ -1514,9 +1496,6 @@ static void iwl_alive_start(struct iwl_priv *priv)
1514 set_bit(STATUS_READY, &priv->status); 1496 set_bit(STATUS_READY, &priv->status);
1515 wake_up_interruptible(&priv->wait_command_queue); 1497 wake_up_interruptible(&priv->wait_command_queue);
1516 1498
1517 if (priv->error_recovering)
1518 iwl_error_recovery(priv);
1519
1520 iwl_power_update_mode(priv, 1); 1499 iwl_power_update_mode(priv, 1);
1521 1500
1522 /* reassociate for ADHOC mode */ 1501 /* reassociate for ADHOC mode */
@@ -1715,9 +1694,6 @@ static int __iwl_up(struct iwl_priv *priv)
1715 continue; 1694 continue;
1716 } 1695 }
1717 1696
1718 /* Clear out the uCode error bit if it is set */
1719 clear_bit(STATUS_FW_ERROR, &priv->status);
1720
1721 /* start card; "initialize" will load runtime ucode */ 1697 /* start card; "initialize" will load runtime ucode */
1722 iwl_nic_start(priv); 1698 iwl_nic_start(priv);
1723 1699
@@ -1812,8 +1788,17 @@ static void iwl_bg_restart(struct work_struct *data)
1812 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 1788 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
1813 return; 1789 return;
1814 1790
1815 iwl_down(priv); 1791 if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
1816 queue_work(priv->workqueue, &priv->up); 1792 mutex_lock(&priv->mutex);
1793 priv->vif = NULL;
1794 priv->is_open = 0;
1795 mutex_unlock(&priv->mutex);
1796 iwl_down(priv);
1797 ieee80211_restart_hw(priv->hw);
1798 } else {
1799 iwl_down(priv);
1800 queue_work(priv->workqueue, &priv->up);
1801 }
1817} 1802}
1818 1803
1819static void iwl_bg_rx_replenish(struct work_struct *data) 1804static void iwl_bg_rx_replenish(struct work_struct *data)
@@ -2007,10 +1992,8 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
2007 1992
2008 IWL_DEBUG_MAC80211(priv, "enter\n"); 1993 IWL_DEBUG_MAC80211(priv, "enter\n");
2009 1994
2010 if (!priv->is_open) { 1995 if (!priv->is_open)
2011 IWL_DEBUG_MAC80211(priv, "leave - skip\n");
2012 return; 1996 return;
2013 }
2014 1997
2015 priv->is_open = 0; 1998 priv->is_open = 0;
2016 1999
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index a9a4fcef7e42..aa1e1dc95ef6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1229,11 +1229,6 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
1229 IWL_DEBUG(priv, IWL_DL_FW_ERRORS, 1229 IWL_DEBUG(priv, IWL_DL_FW_ERRORS,
1230 "Restarting adapter due to uCode error.\n"); 1230 "Restarting adapter due to uCode error.\n");
1231 1231
1232 if (iwl_is_associated(priv)) {
1233 memcpy(&priv->recovery_rxon, &priv->active_rxon,
1234 sizeof(priv->recovery_rxon));
1235 priv->error_recovering = 1;
1236 }
1237 if (priv->cfg->mod_params->restart_fw) 1232 if (priv->cfg->mod_params->restart_fw)
1238 queue_work(priv->workqueue, &priv->restart); 1233 queue_work(priv->workqueue, &priv->restart);
1239 } 1234 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 5aa76a706320..0f2c1b217515 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -933,7 +933,6 @@ struct iwl_priv {
933 const struct iwl_rxon_cmd active_rxon; 933 const struct iwl_rxon_cmd active_rxon;
934 struct iwl_rxon_cmd staging_rxon; 934 struct iwl_rxon_cmd staging_rxon;
935 935
936 int error_recovering;
937 struct iwl_rxon_cmd recovery_rxon; 936 struct iwl_rxon_cmd recovery_rxon;
938 937
939 /* 1st responses from initialize and runtime uCode images. 938 /* 1st responses from initialize and runtime uCode images.
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index f6c1489a0c4a..271e5d1f8425 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1837,23 +1837,6 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
1837 iwl_release_nic_access(priv); 1837 iwl_release_nic_access(priv);
1838} 1838}
1839 1839
1840static void iwl3945_error_recovery(struct iwl_priv *priv)
1841{
1842 unsigned long flags;
1843
1844 memcpy(&priv->staging_rxon, &priv->recovery_rxon,
1845 sizeof(priv->staging_rxon));
1846 priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
1847 iwlcore_commit_rxon(priv);
1848
1849 priv->cfg->ops->smgmt->add_station(priv, priv->bssid, 1, 0, NULL);
1850
1851 spin_lock_irqsave(&priv->lock, flags);
1852 priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
1853 priv->error_recovering = 0;
1854 spin_unlock_irqrestore(&priv->lock, flags);
1855}
1856
1857static void iwl3945_irq_tasklet(struct iwl_priv *priv) 1840static void iwl3945_irq_tasklet(struct iwl_priv *priv)
1858{ 1841{
1859 u32 inta, handled = 0; 1842 u32 inta, handled = 0;
@@ -2683,9 +2666,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
2683 /* After the ALIVE response, we can send commands to 3945 uCode */ 2666 /* After the ALIVE response, we can send commands to 3945 uCode */
2684 set_bit(STATUS_ALIVE, &priv->status); 2667 set_bit(STATUS_ALIVE, &priv->status);
2685 2668
2686 /* Clear out the uCode error bit if it is set */
2687 clear_bit(STATUS_FW_ERROR, &priv->status);
2688
2689 if (iwl_is_rfkill(priv)) 2669 if (iwl_is_rfkill(priv))
2690 return; 2670 return;
2691 2671
@@ -2722,9 +2702,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
2722 set_bit(STATUS_READY, &priv->status); 2702 set_bit(STATUS_READY, &priv->status);
2723 wake_up_interruptible(&priv->wait_command_queue); 2703 wake_up_interruptible(&priv->wait_command_queue);
2724 2704
2725 if (priv->error_recovering)
2726 iwl3945_error_recovery(priv);
2727
2728 /* reassociate for ADHOC mode */ 2705 /* reassociate for ADHOC mode */
2729 if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { 2706 if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
2730 struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, 2707 struct sk_buff *beacon = ieee80211_beacon_get(priv->hw,
@@ -3231,8 +3208,17 @@ static void iwl3945_bg_restart(struct work_struct *data)
3231 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 3208 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3232 return; 3209 return;
3233 3210
3234 iwl3945_down(priv); 3211 if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
3235 queue_work(priv->workqueue, &priv->up); 3212 mutex_lock(&priv->mutex);
3213 priv->vif = NULL;
3214 priv->is_open = 0;
3215 mutex_unlock(&priv->mutex);
3216 iwl3945_down(priv);
3217 ieee80211_restart_hw(priv->hw);
3218 } else {
3219 iwl3945_down(priv);
3220 queue_work(priv->workqueue, &priv->up);
3221 }
3236} 3222}
3237 3223
3238static void iwl3945_bg_rx_replenish(struct work_struct *data) 3224static void iwl3945_bg_rx_replenish(struct work_struct *data)