diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2012-10-25 17:25:52 +0200 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-10-31 17:02:06 +0100 |
commit | f946b529502399d09471c5d13845fefbfe8555a6 (patch) | |
tree | 597c826ef9bfb679fd765796fd3d83845c76d1cc /drivers/net/wireless/iwlwifi/pcie/tx.c | |
parent | 3e2c159260eed10c44f0dd028c328a40a27ad235 (diff) |
iwlwifi: handle RFKILL logic in the transport layer
No HCMD can be sent while RFKILL is asserted. If a SYNC
command is running while RFKILL is asserted the fw will
silently discard it. This means that the driver needs to
wake the process that sleeps on the CMD_SYNC.
Since the RFKILL interrupt is handled in the transport layer
and the code that sleeps in CMD_SYNC is also in the transport
layer, all this logic can be handled there.
This simplifies the work of the op_mode.
So the transport layer will now return -ERFKILL when a CMD
is sent and RFKILL is asserted. This will be the case even
when the CMD is SYNC. The transport layer will return
-ERFKILL straight away.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/pcie/tx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/tx.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 9cb30ae5e9a..ae73bd3944e 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -827,7 +827,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb, IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", trans_pcie_get_cmd_string(trans_pcie, cmd->hdr.cmd)); - wake_up(&trans->wait_command_queue); + wake_up(&trans_pcie->wait_command_queue); } meta->flags = 0; @@ -886,7 +886,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) return ret; } - ret = wait_event_timeout(trans->wait_command_queue, + ret = wait_event_timeout(trans_pcie->wait_command_queue, !test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status), HOST_COMPLETE_TIMEOUT); @@ -915,6 +915,12 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) } } + if (test_bit(STATUS_RFKILL, &trans_pcie->status)) { + IWL_DEBUG_RF_KILL(trans, "RFKILL in SYNC CMD... no rsp\n"); + ret = -ERFKILL; + goto cancel; + } + if ((cmd->flags & CMD_WANT_SKB) && !cmd->resp_pkt) { IWL_ERR(trans, "Error: Response NULL in '%s'\n", trans_pcie_get_cmd_string(trans_pcie, cmd->id)); @@ -946,9 +952,15 @@ cancel: int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + + if (test_bit(STATUS_RFKILL, &trans_pcie->status)) + return -ERFKILL; + if (cmd->flags & CMD_ASYNC) return iwl_send_cmd_async(trans, cmd); + /* We still can fail on RFKILL that can be asserted while we wait */ return iwl_send_cmd_sync(trans, cmd); } |