Skip to content

Commit

Permalink
iwlagn: do not use interruptible waits
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Sep 19, 2011
1 parent 7d8f2d5 commit effd4d9
Show file tree
Hide file tree
Showing 5 changed files with 8 additions and 13 deletions.
9 changes: 2 additions & 7 deletions drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/iwlwifi/iwl-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
/*
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/iwlwifi/iwl-rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit effd4d9

Please sign in to comment.