From f3f911d1773d31f11038d90b04244bc3986c4ccd Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 2 Dec 2008 12:14:04 -0800 Subject: [PATCH] iwlwifi: fix DMA channel number in iwl_txq_ctx_stop The patch fixes the misuse of DMA channel number by Tx queue number in iwl_tx_ctx_stop(). The problem was originally reported by Wu Fengguang who complains iwlagn driver takes too long time when issuing `ifconfig wlan0 down`. The patch now decreases the interface bring down time from 2 seconds to 0.8 second. This fixes bugs: http://bugzilla.kernel.org/show_bug.cgi?id=11956 http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1790 Signed-off-by: Zhu Yi Tested-by: Fengguang Wu Acked-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 4 +++- drivers/net/wireless/iwlwifi/iwl-tx.c | 11 +++++------ 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index f90c9e92ef7..93d3df87fda 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -816,6 +816,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) } priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; + priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; priv->hw_params.scd_bc_tbls_size = IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl); priv->hw_params.max_stations = IWL4965_STATION_COUNT; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index b6c57cbf6f3..f7a8df8dcaa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -827,6 +827,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) } priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; + priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; priv->hw_params.scd_bc_tbls_size = IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl); priv->hw_params.max_stations = IWL5000_STATION_COUNT; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 846b8b01fa7..5f6805bfec3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -508,6 +508,7 @@ struct iwl_sensitivity_ranges { /** * struct iwl_hw_params * @max_txq_num: Max # Tx queues supported + * @dma_chnl_num: Number of Tx DMA/FIFO channels * @scd_bc_tbls_size: size of scheduler byte count tables * @tx/rx_chains_num: Number of TX/RX chains * @valid_tx/rx_ant: usable antennas @@ -525,7 +526,8 @@ struct iwl_sensitivity_ranges { * @struct iwl_sensitivity_ranges: range of sensitivity values */ struct iwl_hw_params { - u16 max_txq_num; + u8 max_txq_num; + u8 dma_chnl_num; u16 scd_bc_tbls_size; u8 tx_chains_num; u8 rx_chains_num; diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index e045dfeaa1f..18d6cf67d9b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -611,7 +611,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) */ void iwl_txq_ctx_stop(struct iwl_priv *priv) { - int txq_id; + int ch; unsigned long flags; /* Turn off all Tx DMA fifos */ @@ -624,12 +624,11 @@ void iwl_txq_ctx_stop(struct iwl_priv *priv) priv->cfg->ops->lib->txq_set_sched(priv, 0); /* Stop each Tx DMA channel, and wait for it to be idle */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { - iwl_write_direct32(priv, - FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), 0x0); + for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, - FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE - (txq_id), 200); + FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), + 200); } iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); -- 2.41.1