diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2013-12-19 20:19:17 (GMT) |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2013-12-31 17:03:45 (GMT) |
commit | fba1c62766340d3a6736c616a36494abb700dae8 (patch) | |
tree | aa0e3b69475182a0cd519529c73d155520c7f30f | |
parent | 3dc3374fcebe30fefebf1fdce660d33b3e2bd0f9 (diff) | |
download | linux-fba1c62766340d3a6736c616a36494abb700dae8.tar.xz |
iwlwifi: pcie: allow the op_mode to call stop_device whenever it wants
Calling stop_device when start_fw wasn't called would issue:
Stopping tx queues that aren't allocated...
Also allow the op_mode to call stop_device and then to
disable the Tx queues - in that case just silently ignore
the disabling on the Tx queues, since the PRPH registers
aren't reachable any more.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/tx.c | 23 |
2 files changed, 22 insertions, 8 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 0c36478..04e1826 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -622,6 +622,10 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, { int ret; + if (unlikely(!(cmd->flags & CMD_SEND_IN_RFKILL) && + test_bit(STATUS_RFKILL, &trans->status))) + return -ERFKILL; + if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) return -EIO; @@ -684,9 +688,6 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue) { - if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) - IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); - trans->ops->txq_disable(trans, queue); } diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 2417af9..aec9d9f 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -758,11 +758,17 @@ int iwl_pcie_tx_stop(struct iwl_trans *trans) } spin_unlock(&trans_pcie->irq_lock); - if (!trans_pcie->txq) { - IWL_WARN(trans, - "Stopping tx queues that aren't allocated...\n"); + /* + * This function can be called before the op_mode disabled the + * queues. This happens when we have an rfkill interrupt. + * Since we stop Tx altogether - mark the queues as stopped. + */ + memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped)); + memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used)); + + /* This can happen: start_hw, stop_device */ + if (!trans_pcie->txq) return 0; - } /* Unmap DMA from host system and free skb's */ for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; @@ -1150,8 +1156,15 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) SCD_TX_STTS_QUEUE_OFFSET(txq_id); static const u32 zero_val[4] = {}; + /* + * Upon HW Rfkill - we stop the device, and then stop the queues + * in the op_mode. Just for the sake of the simplicity of the op_mode, + * allow the op_mode to call txq_disable after it already called + * stop_device. + */ if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { - WARN_ONCE(1, "queue %d not used", txq_id); + WARN_ONCE(test_bit(STATUS_DEVICE_ENABLED, &trans->status), + "queue %d not used", txq_id); return; } |