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 <yi.zhu@intel.com> Tested-by: Fengguang Wu <fengguang.wu@intel.com> Acked-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
@@ -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.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 =
|
priv->hw_params.scd_bc_tbls_size =
|
||||||
IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl);
|
IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl);
|
||||||
priv->hw_params.max_stations = IWL4965_STATION_COUNT;
|
priv->hw_params.max_stations = IWL4965_STATION_COUNT;
|
||||||
|
@@ -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.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 =
|
priv->hw_params.scd_bc_tbls_size =
|
||||||
IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl);
|
IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl);
|
||||||
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
|
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
|
||||||
|
@@ -508,6 +508,7 @@ struct iwl_sensitivity_ranges {
|
|||||||
/**
|
/**
|
||||||
* struct iwl_hw_params
|
* struct iwl_hw_params
|
||||||
* @max_txq_num: Max # Tx queues supported
|
* @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
|
* @scd_bc_tbls_size: size of scheduler byte count tables
|
||||||
* @tx/rx_chains_num: Number of TX/RX chains
|
* @tx/rx_chains_num: Number of TX/RX chains
|
||||||
* @valid_tx/rx_ant: usable antennas
|
* @valid_tx/rx_ant: usable antennas
|
||||||
@@ -525,7 +526,8 @@ struct iwl_sensitivity_ranges {
|
|||||||
* @struct iwl_sensitivity_ranges: range of sensitivity values
|
* @struct iwl_sensitivity_ranges: range of sensitivity values
|
||||||
*/
|
*/
|
||||||
struct iwl_hw_params {
|
struct iwl_hw_params {
|
||||||
u16 max_txq_num;
|
u8 max_txq_num;
|
||||||
|
u8 dma_chnl_num;
|
||||||
u16 scd_bc_tbls_size;
|
u16 scd_bc_tbls_size;
|
||||||
u8 tx_chains_num;
|
u8 tx_chains_num;
|
||||||
u8 rx_chains_num;
|
u8 rx_chains_num;
|
||||||
|
@@ -611,7 +611,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
|
|||||||
*/
|
*/
|
||||||
void iwl_txq_ctx_stop(struct iwl_priv *priv)
|
void iwl_txq_ctx_stop(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
int txq_id;
|
int ch;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
/* Turn off all Tx DMA fifos */
|
/* 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);
|
priv->cfg->ops->lib->txq_set_sched(priv, 0);
|
||||||
|
|
||||||
/* Stop each Tx DMA channel, and wait for it to be idle */
|
/* 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++) {
|
for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) {
|
||||||
iwl_write_direct32(priv,
|
iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
|
||||||
FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), 0x0);
|
|
||||||
iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
|
iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
|
||||||
FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE
|
FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
|
||||||
(txq_id), 200);
|
200);
|
||||||
}
|
}
|
||||||
iwl_release_nic_access(priv);
|
iwl_release_nic_access(priv);
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
Reference in New Issue
Block a user