diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e8f405a01e3d..a4e8db35a559 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1266,15 +1266,24 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) * 3- update RX shared data to indicate last write index. * 4- send interrupt. * This could lead to RX race, driver could receive RX interrupt - * but the shared data changes does not reflect this. - * this could lead to RX race, RX periodic will solve this race + * but the shared data changes does not reflect this; + * periodic interrupt will detect any dangling Rx activity. */ - iwl_write32(priv, CSR_INT_PERIODIC_REG, + + /* Disable periodic interrupt; we use it as just a one-shot. */ + iwl_write8(priv, CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_DIS); iwl_rx_handle(priv); - /* Only set RX periodic if real RX is received. */ + + /* + * Enable periodic interrupt in 8 msec only if we received + * real RX interrupt (instead of just periodic int), to catch + * any dangling Rx interrupt. If it was just the periodic + * interrupt, there was no dangling Rx activity, and no need + * to extend the periodic interrupt; one-shot is enough. + */ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) - iwl_write32(priv, CSR_INT_PERIODIC_REG, + iwl_write8(priv, CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_ENA); priv->isr_stats.rx++; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index a2636f4b068f..c25cab5d0451 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -255,7 +255,10 @@ int iwl_hw_nic_init(struct iwl_priv *priv) /* nic_init */ spin_lock_irqsave(&priv->lock, flags); priv->cfg->ops->lib->apm_ops.init(priv); - iwl_write32(priv, CSR_INT_COALESCING, 512 / 32); + + /* Set interrupt coalescing timer to 512 usecs */ + iwl_write8(priv, CSR_INT_COALESCING, 512 / 32); + spin_unlock_irqrestore(&priv->lock, flags); ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 68ed82206723..a7bfae01f19b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -173,8 +173,8 @@ #define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */ #define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) /* WAKE_ME */ -#define CSR_INT_PERIODIC_DIS (0x00) -#define CSR_INT_PERIODIC_ENA (0xFF) +#define CSR_INT_PERIODIC_DIS (0x00) /* disable periodic int*/ +#define CSR_INT_PERIODIC_ENA (0xFF) /* 255*32 usec ~ 8 msec*/ /* interrupt flags in INTA, set by uCode or hardware (e.g. dma), * acknowledged (reset) by host writing "1" to flagged bits. */ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index cc980d5d57c2..6090bc15a6d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -477,7 +477,8 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); - iwl_write32(priv, CSR_INT_COALESCING, 0x40); + /* Set interrupt coalescing timer to 64 x 32 = 2048 usecs */ + iwl_write8(priv, CSR_INT_COALESCING, 0x40); return 0; }