|
@@ -725,33 +725,50 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans)
|
|
|
iwl_pcie_tx_start(trans, 0);
|
|
iwl_pcie_tx_start(trans, 0);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void iwl_pcie_tx_stop_fh(struct iwl_trans *trans)
|
|
|
|
|
+{
|
|
|
|
|
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
|
|
|
|
+ unsigned long flags;
|
|
|
|
|
+ int ch, ret;
|
|
|
|
|
+ u32 mask = 0;
|
|
|
|
|
+
|
|
|
|
|
+ spin_lock(&trans_pcie->irq_lock);
|
|
|
|
|
+
|
|
|
|
|
+ if (!iwl_trans_grab_nic_access(trans, false, &flags))
|
|
|
|
|
+ goto out;
|
|
|
|
|
+
|
|
|
|
|
+ /* Stop each Tx DMA channel */
|
|
|
|
|
+ for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) {
|
|
|
|
|
+ iwl_write32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
|
|
|
|
|
+ mask |= FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Wait for DMA channels to be idle */
|
|
|
|
|
+ ret = iwl_poll_bit(trans, FH_TSSR_TX_STATUS_REG, mask, mask, 5000);
|
|
|
|
|
+ if (ret < 0)
|
|
|
|
|
+ IWL_ERR(trans,
|
|
|
|
|
+ "Failing on timeout while stopping DMA channel %d [0x%08x]\n",
|
|
|
|
|
+ ch, iwl_read32(trans, FH_TSSR_TX_STATUS_REG));
|
|
|
|
|
+
|
|
|
|
|
+ iwl_trans_release_nic_access(trans, &flags);
|
|
|
|
|
+
|
|
|
|
|
+out:
|
|
|
|
|
+ spin_unlock(&trans_pcie->irq_lock);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* iwl_pcie_tx_stop - Stop all Tx DMA channels
|
|
* iwl_pcie_tx_stop - Stop all Tx DMA channels
|
|
|
*/
|
|
*/
|
|
|
int iwl_pcie_tx_stop(struct iwl_trans *trans)
|
|
int iwl_pcie_tx_stop(struct iwl_trans *trans)
|
|
|
{
|
|
{
|
|
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
|
|
- int ch, txq_id, ret;
|
|
|
|
|
|
|
+ int txq_id;
|
|
|
|
|
|
|
|
/* Turn off all Tx DMA fifos */
|
|
/* Turn off all Tx DMA fifos */
|
|
|
- spin_lock(&trans_pcie->irq_lock);
|
|
|
|
|
-
|
|
|
|
|
iwl_scd_deactivate_fifos(trans);
|
|
iwl_scd_deactivate_fifos(trans);
|
|
|
|
|
|
|
|
- /* Stop each Tx DMA channel, and wait for it to be idle */
|
|
|
|
|
- for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) {
|
|
|
|
|
- iwl_write_direct32(trans,
|
|
|
|
|
- FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
|
|
|
|
|
- ret = iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG,
|
|
|
|
|
- FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000);
|
|
|
|
|
- if (ret < 0)
|
|
|
|
|
- IWL_ERR(trans,
|
|
|
|
|
- "Failing on timeout while stopping DMA channel %d [0x%08x]\n",
|
|
|
|
|
- ch,
|
|
|
|
|
- iwl_read_direct32(trans,
|
|
|
|
|
- FH_TSSR_TX_STATUS_REG));
|
|
|
|
|
- }
|
|
|
|
|
- spin_unlock(&trans_pcie->irq_lock);
|
|
|
|
|
|
|
+ /* Turn off all Tx DMA channels */
|
|
|
|
|
+ iwl_pcie_tx_stop_fh(trans);
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
* This function can be called before the op_mode disabled the
|
|
* This function can be called before the op_mode disabled the
|