aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorStanislaw Gruszka <sgruszka@redhat.com>2012-01-13 06:59:32 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-01-13 14:40:57 -0500
commitdfd00c4c8f3dfa1fd7cec45f83d98b2a49743dcd (patch)
tree918140b949cc6189294d27f688925cc3a763ed63 /drivers/net
parent92c1ff1fa772ee76a18ae1edd2e4baecf381f17e (diff)
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 4ba7d9997869d25bd223dea7536fc1ce9fab3b3b "rt2800pci: handle spurious interrupts", but it was reverted in commit 82e5fc2a34fa9ffea38f00c4066b7e600a0ca5e6 as thing, that will prevent to detect real spurious interrupts. Reported-and-tested-by: Amir Hedayaty <hedayaty@gmail.com> Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> Acked-by: Gertjan van Wingerde <gwingerde@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c28
1 files changed, 8 insertions, 20 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 4941a1a23219..dc88baefa72e 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -422,7 +422,6 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
422static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, 422static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
423 enum dev_state state) 423 enum dev_state state)
424{ 424{
425 int mask = (state == STATE_RADIO_IRQ_ON);
426 u32 reg; 425 u32 reg;
427 unsigned long flags; 426 unsigned long flags;
428 427
@@ -436,25 +435,14 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
436 } 435 }
437 436
438 spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); 437 spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
439 rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg); 438 reg = 0;
440 rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0); 439 if (state == STATE_RADIO_IRQ_ON) {
441 rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0); 440 rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, 1);
442 rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, mask); 441 rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, 1);
443 rt2x00_set_field32(&reg, INT_MASK_CSR_AC0_DMA_DONE, 0); 442 rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, 1);
444 rt2x00_set_field32(&reg, INT_MASK_CSR_AC1_DMA_DONE, 0); 443 rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
445 rt2x00_set_field32(&reg, INT_MASK_CSR_AC2_DMA_DONE, 0); 444 rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, 1);
446 rt2x00_set_field32(&reg, INT_MASK_CSR_AC3_DMA_DONE, 0); 445 }
447 rt2x00_set_field32(&reg, INT_MASK_CSR_HCCA_DMA_DONE, 0);
448 rt2x00_set_field32(&reg, INT_MASK_CSR_MGMT_DMA_DONE, 0);
449 rt2x00_set_field32(&reg, INT_MASK_CSR_MCU_COMMAND, 0);
450 rt2x00_set_field32(&reg, INT_MASK_CSR_RXTX_COHERENT, 0);
451 rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, mask);
452 rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, mask);
453 rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, mask);
454 rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, mask);
455 rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, 0);
456 rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
457 rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
458 rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); 446 rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
459 spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); 447 spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
460 448