Commit dfd00c4c authored by Stanislaw Gruszka's avatar Stanislaw Gruszka Committed by John W. Linville

rt2800pci: fix spurious interrupts generation

Same devices can generate interrupt without properly setting bit in
INT_SOURCE_CSR register (spurious interrupt), what will cause IRQ line
will be disabled by interrupts controller driver.

We discovered that clearing INT_MASK_CSR stops such behaviour. We
previously first read that register, and then clear all know interrupt
sources bits and do not touch reserved bits. After this patch, we write
to all register content (I believe writing to reserved bits on that
register will not cause any problems, I tested that on my rt2800pci
device).

This fix very bad performance problem, practically making device
unusable (since worked without interrupts), reported in:
https://bugzilla.redhat.com/show_bug.cgi?id=658451

We previously tried to workaround that issue in commit
4ba7d999 "rt2800pci: handle spurious
interrupts", but it was reverted in commit
82e5fc2a
as thing, that will prevent to detect real spurious interrupts.
Reported-and-tested-by: default avatarAmir Hedayaty <hedayaty@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarStanislaw Gruszka <sgruszka@redhat.com>
Acked-by: default avatarGertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 92c1ff1f
......@@ -422,7 +422,6 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
int mask = (state == STATE_RADIO_IRQ_ON);
u32 reg;
unsigned long flags;
......@@ -436,25 +435,14 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
}
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_AC0_DMA_DONE, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_AC1_DMA_DONE, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_AC2_DMA_DONE, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_AC3_DMA_DONE, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_HCCA_DMA_DONE, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_MGMT_DMA_DONE, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_MCU_COMMAND, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_RXTX_COHERENT, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
reg = 0;
if (state == STATE_RADIO_IRQ_ON) {
rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, 1);
rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, 1);
rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, 1);
rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, 1);
}
rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment