aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-09-15 14:46:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-09-19 16:10:10 -0400
commiteffd4d9aece9184f526e6556786a94d335e38b71 (patch)
tree193f5f428dca02fc307043648e62ef0d62e59ca0
parent7d8f2d50b5082385ad0e0ab5f7dc2a6f1c19819c (diff)
iwlagn: do not use interruptible waits
Since the dawn of its time, iwlwifi has used interruptible waits to wait for synchronous commands and firmware loading. This leads to "interesting" bugs, because it can't actually handle the interruptions; for example when a command sending is interrupted it will assume the command completed fully, and then leave it pending, which leads to all kinds of trouble when the command finishes later. Since there's no easy way to gracefully deal with interruptions, fix the driver to not use interruptible waits. This at least fixes the error iwlagn 0000:02:00.0: Error: Response NULL in 'REPLY_SCAN_ABORT_CMD' I have seen in P2P testing, but it is likely that there are other errors caused by this. Cc: Stanislaw Gruszka <sgruszka@redhat.com> Cc: stable@kernel.org [2.6.24+] Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-ucode.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c4
5 files changed, 8 insertions, 13 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 5f8d7b61db4a..b5bae38eff83 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -114,13 +114,8 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
114 FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); 114 FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
115 115
116 IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name); 116 IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name);
117 ret = wait_event_interruptible_timeout(priv->shrd->wait_command_queue, 117 ret = wait_event_timeout(priv->shrd->wait_command_queue,
118 priv->ucode_write_complete, 5 * HZ); 118 priv->ucode_write_complete, 5 * HZ);
119 if (ret == -ERESTARTSYS) {
120 IWL_ERR(priv, "Could not load the %s uCode section due "
121 "to interrupt\n", name);
122 return ret;
123 }
124 if (!ret) { 119 if (!ret) {
125 IWL_ERR(priv, "Could not load the %s uCode section\n", 120 IWL_ERR(priv, "Could not load the %s uCode section\n",
126 name); 121 name);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index ce8a015c7205..cea6520fafdb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -869,7 +869,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
869 * commands by clearing the ready bit */ 869 * commands by clearing the ready bit */
870 clear_bit(STATUS_READY, &priv->shrd->status); 870 clear_bit(STATUS_READY, &priv->shrd->status);
871 871
872 wake_up_interruptible(&priv->shrd->wait_command_queue); 872 wake_up(&priv->shrd->wait_command_queue);
873 873
874 if (!ondemand) { 874 if (!ondemand) {
875 /* 875 /*
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index c7e6a746c3ea..2ee61031e207 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -644,7 +644,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
644 wiphy_rfkill_set_hw_state(priv->hw->wiphy, 644 wiphy_rfkill_set_hw_state(priv->hw->wiphy,
645 test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); 645 test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
646 else 646 else
647 wake_up_interruptible(&priv->shrd->wait_command_queue); 647 wake_up(&priv->shrd->wait_command_queue);
648} 648}
649 649
650static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, 650static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
index 458a6fbc2e39..6f3f07dd817d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
@@ -657,7 +657,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans)
657 */ 657 */
658 clear_bit(STATUS_READY, &trans->shrd->status); 658 clear_bit(STATUS_READY, &trans->shrd->status);
659 clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); 659 clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
660 wake_up_interruptible(&priv->shrd->wait_command_queue); 660 wake_up(&priv->shrd->wait_command_queue);
661 IWL_ERR(trans, "RF is used by WiMAX\n"); 661 IWL_ERR(trans, "RF is used by WiMAX\n");
662 return; 662 return;
663 } 663 }
@@ -1098,7 +1098,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
1098 handled |= CSR_INT_BIT_FH_TX; 1098 handled |= CSR_INT_BIT_FH_TX;
1099 /* Wake up uCode load routine, now that load is complete */ 1099 /* Wake up uCode load routine, now that load is complete */
1100 priv(trans)->ucode_write_complete = 1; 1100 priv(trans)->ucode_write_complete = 1;
1101 wake_up_interruptible(&trans->shrd->wait_command_queue); 1101 wake_up(&trans->shrd->wait_command_queue);
1102 } 1102 }
1103 1103
1104 if (inta & ~handled) { 1104 if (inta & ~handled) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
index 93d22c470e2f..62c00523b3bf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
@@ -946,7 +946,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb)
946 clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); 946 clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
947 IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", 947 IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
948 get_cmd_string(cmd->hdr.cmd)); 948 get_cmd_string(cmd->hdr.cmd));
949 wake_up_interruptible(&trans->shrd->wait_command_queue); 949 wake_up(&trans->shrd->wait_command_queue);
950 } 950 }
951 951
952 meta->flags = 0; 952 meta->flags = 0;
@@ -1032,7 +1032,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
1032 return ret; 1032 return ret;
1033 } 1033 }
1034 1034
1035 ret = wait_event_interruptible_timeout(trans->shrd->wait_command_queue, 1035 ret = wait_event_timeout(trans->shrd->wait_command_queue,
1036 !test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status), 1036 !test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status),
1037 HOST_COMPLETE_TIMEOUT); 1037 HOST_COMPLETE_TIMEOUT);
1038 if (!ret) { 1038 if (!ret) {