iwlagn: do not use interruptible waits
authorJohannes Berg <johannes.berg@intel.com>
Thu, 15 Sep 2011 18:46:52 +0000 (11:46 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 19 Sep 2011 20:10:10 +0000 (16:10 -0400)
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>
drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-rx.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c

index 5f8d7b61db4adfe2b66e7d59ab1e7cfcdd4fda74..b5bae38eff83de21f22fc4020901f7372ddba116 100644 (file)
@@ -114,13 +114,8 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
                FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
 
        IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name);
-       ret = wait_event_interruptible_timeout(priv->shrd->wait_command_queue,
-                                       priv->ucode_write_complete, 5 * HZ);
-       if (ret == -ERESTARTSYS) {
-               IWL_ERR(priv, "Could not load the %s uCode section due "
-                       "to interrupt\n", name);
-               return ret;
-       }
+       ret = wait_event_timeout(priv->shrd->wait_command_queue,
+                                priv->ucode_write_complete, 5 * HZ);
        if (!ret) {
                IWL_ERR(priv, "Could not load the %s uCode section\n",
                        name);
index ce8a015c7205c8dc39f4142fb718dd923a368341..cea6520fafdb27789de270af3357e7b8739409d5 100644 (file)
@@ -869,7 +869,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
         * commands by clearing the ready bit */
        clear_bit(STATUS_READY, &priv->shrd->status);
 
-       wake_up_interruptible(&priv->shrd->wait_command_queue);
+       wake_up(&priv->shrd->wait_command_queue);
 
        if (!ondemand) {
                /*
index c7e6a746c3ea49dc10d0206badfa47ad4bb5043b..2ee61031e207b8357e63f40eea6ce2a95f0eb4b4 100644 (file)
@@ -644,7 +644,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
                wiphy_rfkill_set_hw_state(priv->hw->wiphy,
                        test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
        else
-               wake_up_interruptible(&priv->shrd->wait_command_queue);
+               wake_up(&priv->shrd->wait_command_queue);
 }
 
 static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
index 458a6fbc2e39f6fb80eccaf971d0155e400bf48b..6f3f07dd817da308e2fefe83634ab2f47449484d 100644 (file)
@@ -657,7 +657,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans)
                 */
                clear_bit(STATUS_READY, &trans->shrd->status);
                clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
-               wake_up_interruptible(&priv->shrd->wait_command_queue);
+               wake_up(&priv->shrd->wait_command_queue);
                IWL_ERR(trans, "RF is used by WiMAX\n");
                return;
        }
@@ -1098,7 +1098,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
                handled |= CSR_INT_BIT_FH_TX;
                /* Wake up uCode load routine, now that load is complete */
                priv(trans)->ucode_write_complete = 1;
-               wake_up_interruptible(&trans->shrd->wait_command_queue);
+               wake_up(&trans->shrd->wait_command_queue);
        }
 
        if (inta & ~handled) {
index 93d22c470e2fd11933b3f5d770fc521e05a7b8a9..62c00523b3bf9ec42410f0c82249125cb6294e57 100644 (file)
@@ -946,7 +946,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb)
                clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
                IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
                               get_cmd_string(cmd->hdr.cmd));
-               wake_up_interruptible(&trans->shrd->wait_command_queue);
+               wake_up(&trans->shrd->wait_command_queue);
        }
 
        meta->flags = 0;
@@ -1032,7 +1032,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
                return ret;
        }
 
-       ret = wait_event_interruptible_timeout(trans->shrd->wait_command_queue,
+       ret = wait_event_timeout(trans->shrd->wait_command_queue,
                        !test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status),
                        HOST_COMPLETE_TIMEOUT);
        if (!ret) {