diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-05-08 16:44:36 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-05-11 15:23:57 -0400 |
commit | 19cc10870ece942d287241937944c237130f50f4 (patch) | |
tree | bda1c1eb5750159c3470ca66607e7050dfc8d49c /drivers | |
parent | 44033f80cefd1d7b474efdabc412476d4bafb8f4 (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.c | 43 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 36 |
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 | ||
970 | static 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 | |||
987 | static void iwl_irq_tasklet(struct iwl_priv *priv) | 969 | static 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 | ||
1819 | static void iwl_bg_rx_replenish(struct work_struct *data) | 1804 | static 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 | ||
1840 | static 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 | |||
1857 | static void iwl3945_irq_tasklet(struct iwl_priv *priv) | 1840 | static 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 | ||
3238 | static void iwl3945_bg_rx_replenish(struct work_struct *data) | 3224 | static void iwl3945_bg_rx_replenish(struct work_struct *data) |