diff options
author | David S. Miller <davem@davemloft.net> | 2011-04-12 19:16:02 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-04-12 19:16:02 -0400 |
commit | a7e70158884629898d79709622a66b8ef99e4018 (patch) | |
tree | bd0cd03816f85f5bcef84000e01b0f9701f063ed /drivers/net/wireless/iwlwifi/iwl-core.c | |
parent | 24743537d3f784a8b3014e934fad0a9c45e4e789 (diff) | |
parent | 252f4bf400df1712408fe83ba199a66a1b57ab1d (diff) |
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-core.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 114 |
1 files changed, 54 insertions, 60 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index bafbe57c9602..45ec5cfe3fcf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * GPL LICENSE SUMMARY | 3 | * GPL LICENSE SUMMARY |
4 | * | 4 | * |
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of version 2 of the GNU General Public License as | 8 | * it under the terms of version 2 of the GNU General Public License as |
@@ -890,10 +890,8 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv, | |||
890 | IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); | 890 | IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); |
891 | } | 891 | } |
892 | #endif | 892 | #endif |
893 | /** | 893 | |
894 | * iwl_irq_handle_error - called for HW or SW error interrupt from card | 894 | void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) |
895 | */ | ||
896 | void iwl_irq_handle_error(struct iwl_priv *priv) | ||
897 | { | 895 | { |
898 | unsigned int reload_msec; | 896 | unsigned int reload_msec; |
899 | unsigned long reload_jiffies; | 897 | unsigned long reload_jiffies; |
@@ -904,18 +902,62 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
904 | /* Cancel currently queued command. */ | 902 | /* Cancel currently queued command. */ |
905 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 903 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
906 | 904 | ||
905 | /* Keep the restart process from trying to send host | ||
906 | * commands by clearing the ready bit */ | ||
907 | clear_bit(STATUS_READY, &priv->status); | ||
908 | |||
909 | wake_up_interruptible(&priv->wait_command_queue); | ||
910 | |||
911 | if (!ondemand) { | ||
912 | /* | ||
913 | * If firmware keep reloading, then it indicate something | ||
914 | * serious wrong and firmware having problem to recover | ||
915 | * from it. Instead of keep trying which will fill the syslog | ||
916 | * and hang the system, let's just stop it | ||
917 | */ | ||
918 | reload_jiffies = jiffies; | ||
919 | reload_msec = jiffies_to_msecs((long) reload_jiffies - | ||
920 | (long) priv->reload_jiffies); | ||
921 | priv->reload_jiffies = reload_jiffies; | ||
922 | if (reload_msec <= IWL_MIN_RELOAD_DURATION) { | ||
923 | priv->reload_count++; | ||
924 | if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) { | ||
925 | IWL_ERR(priv, "BUG_ON, Stop restarting\n"); | ||
926 | return; | ||
927 | } | ||
928 | } else | ||
929 | priv->reload_count = 0; | ||
930 | } | ||
931 | |||
932 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { | ||
933 | if (priv->cfg->mod_params->restart_fw) { | ||
934 | IWL_DEBUG(priv, IWL_DL_FW_ERRORS, | ||
935 | "Restarting adapter due to uCode error.\n"); | ||
936 | queue_work(priv->workqueue, &priv->restart); | ||
937 | } else | ||
938 | IWL_DEBUG(priv, IWL_DL_FW_ERRORS, | ||
939 | "Detected FW error, but not restarting\n"); | ||
940 | } | ||
941 | } | ||
942 | |||
943 | /** | ||
944 | * iwl_irq_handle_error - called for HW or SW error interrupt from card | ||
945 | */ | ||
946 | void iwl_irq_handle_error(struct iwl_priv *priv) | ||
947 | { | ||
907 | /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ | 948 | /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ |
908 | if (priv->cfg->internal_wimax_coex && | 949 | if (priv->cfg->internal_wimax_coex && |
909 | (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) & | 950 | (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) & |
910 | APMS_CLK_VAL_MRB_FUNC_MODE) || | 951 | APMS_CLK_VAL_MRB_FUNC_MODE) || |
911 | (iwl_read_prph(priv, APMG_PS_CTRL_REG) & | 952 | (iwl_read_prph(priv, APMG_PS_CTRL_REG) & |
912 | APMG_PS_CTRL_VAL_RESET_REQ))) { | 953 | APMG_PS_CTRL_VAL_RESET_REQ))) { |
913 | wake_up_interruptible(&priv->wait_command_queue); | ||
914 | /* | 954 | /* |
915 | *Keep the restart process from trying to send host | 955 | * Keep the restart process from trying to send host |
916 | * commands by clearing the INIT status bit | 956 | * commands by clearing the ready bit. |
917 | */ | 957 | */ |
918 | clear_bit(STATUS_READY, &priv->status); | 958 | clear_bit(STATUS_READY, &priv->status); |
959 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | ||
960 | wake_up_interruptible(&priv->wait_command_queue); | ||
919 | IWL_ERR(priv, "RF is used by WiMAX\n"); | 961 | IWL_ERR(priv, "RF is used by WiMAX\n"); |
920 | return; | 962 | return; |
921 | } | 963 | } |
@@ -935,38 +977,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
935 | &priv->contexts[IWL_RXON_CTX_BSS]); | 977 | &priv->contexts[IWL_RXON_CTX_BSS]); |
936 | #endif | 978 | #endif |
937 | 979 | ||
938 | wake_up_interruptible(&priv->wait_command_queue); | 980 | iwlagn_fw_error(priv, false); |
939 | |||
940 | /* Keep the restart process from trying to send host | ||
941 | * commands by clearing the INIT status bit */ | ||
942 | clear_bit(STATUS_READY, &priv->status); | ||
943 | |||
944 | /* | ||
945 | * If firmware keep reloading, then it indicate something | ||
946 | * serious wrong and firmware having problem to recover | ||
947 | * from it. Instead of keep trying which will fill the syslog | ||
948 | * and hang the system, let's just stop it | ||
949 | */ | ||
950 | reload_jiffies = jiffies; | ||
951 | reload_msec = jiffies_to_msecs((long) reload_jiffies - | ||
952 | (long) priv->reload_jiffies); | ||
953 | priv->reload_jiffies = reload_jiffies; | ||
954 | if (reload_msec <= IWL_MIN_RELOAD_DURATION) { | ||
955 | priv->reload_count++; | ||
956 | if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) { | ||
957 | IWL_ERR(priv, "BUG_ON, Stop restarting\n"); | ||
958 | return; | ||
959 | } | ||
960 | } else | ||
961 | priv->reload_count = 0; | ||
962 | |||
963 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { | ||
964 | IWL_DEBUG(priv, IWL_DL_FW_ERRORS, | ||
965 | "Restarting adapter due to uCode error.\n"); | ||
966 | |||
967 | if (priv->cfg->mod_params->restart_fw) | ||
968 | queue_work(priv->workqueue, &priv->restart); | ||
969 | } | ||
970 | } | 981 | } |
971 | 982 | ||
972 | static int iwl_apm_stop_master(struct iwl_priv *priv) | 983 | static int iwl_apm_stop_master(struct iwl_priv *priv) |
@@ -1094,21 +1105,13 @@ int iwl_apm_init(struct iwl_priv *priv) | |||
1094 | } | 1105 | } |
1095 | 1106 | ||
1096 | /* | 1107 | /* |
1097 | * Enable DMA and BSM (if used) clocks, wait for them to stabilize. | 1108 | * Enable DMA clock and wait for it to stabilize. |
1098 | * BSM (Boostrap State Machine) is only in 3945 and 4965; | ||
1099 | * later devices (i.e. 5000 and later) have non-volatile SRAM, | ||
1100 | * and don't need BSM to restore data after power-saving sleep. | ||
1101 | * | 1109 | * |
1102 | * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits | 1110 | * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits |
1103 | * do not disable clocks. This preserves any hardware bits already | 1111 | * do not disable clocks. This preserves any hardware bits already |
1104 | * set by default in "CLK_CTRL_REG" after reset. | 1112 | * set by default in "CLK_CTRL_REG" after reset. |
1105 | */ | 1113 | */ |
1106 | if (priv->cfg->base_params->use_bsm) | 1114 | iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); |
1107 | iwl_write_prph(priv, APMG_CLK_EN_REG, | ||
1108 | APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); | ||
1109 | else | ||
1110 | iwl_write_prph(priv, APMG_CLK_EN_REG, | ||
1111 | APMG_CLK_VAL_DMA_CLK_RQT); | ||
1112 | udelay(20); | 1115 | udelay(20); |
1113 | 1116 | ||
1114 | /* Disable L1-Active */ | 1117 | /* Disable L1-Active */ |
@@ -1430,7 +1433,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
1430 | 1433 | ||
1431 | iwl_teardown_interface(priv, vif, false); | 1434 | iwl_teardown_interface(priv, vif, false); |
1432 | 1435 | ||
1433 | memset(priv->bssid, 0, ETH_ALEN); | ||
1434 | mutex_unlock(&priv->mutex); | 1436 | mutex_unlock(&priv->mutex); |
1435 | 1437 | ||
1436 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1438 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
@@ -1756,15 +1758,7 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) | |||
1756 | break; | 1758 | break; |
1757 | } | 1759 | } |
1758 | IWL_ERR(priv, "On demand firmware reload\n"); | 1760 | IWL_ERR(priv, "On demand firmware reload\n"); |
1759 | /* Set the FW error flag -- cleared on iwl_down */ | 1761 | iwlagn_fw_error(priv, true); |
1760 | set_bit(STATUS_FW_ERROR, &priv->status); | ||
1761 | wake_up_interruptible(&priv->wait_command_queue); | ||
1762 | /* | ||
1763 | * Keep the restart process from trying to send host | ||
1764 | * commands by clearing the INIT status bit | ||
1765 | */ | ||
1766 | clear_bit(STATUS_READY, &priv->status); | ||
1767 | queue_work(priv->workqueue, &priv->restart); | ||
1768 | break; | 1762 | break; |
1769 | } | 1763 | } |
1770 | return 0; | 1764 | return 0; |