mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
3dc3374fce
commit
fba1c62766
|
@ -622,6 +622,10 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
|
||||||
{
|
{
|
||||||
int ret;
|
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)))
|
if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
|
||||||
return -EIO;
|
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)
|
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);
|
trans->ops->txq_disable(trans, queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -758,11 +758,17 @@ int iwl_pcie_tx_stop(struct iwl_trans *trans)
|
||||||
}
|
}
|
||||||
spin_unlock(&trans_pcie->irq_lock);
|
spin_unlock(&trans_pcie->irq_lock);
|
||||||
|
|
||||||
if (!trans_pcie->txq) {
|
/*
|
||||||
IWL_WARN(trans,
|
* This function can be called before the op_mode disabled the
|
||||||
"Stopping tx queues that aren't allocated...\n");
|
* 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;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmap DMA from host system and free skb's */
|
/* Unmap DMA from host system and free skb's */
|
||||||
for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
|
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);
|
SCD_TX_STTS_QUEUE_OFFSET(txq_id);
|
||||||
static const u32 zero_val[4] = {};
|
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)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue