aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorStanislaw Gruszka <sgruszka@redhat.com>2012-01-13 06:59:32 -0500
committerHerton Ronaldo Krzesinski <herton.krzesinski@canonical.com>2012-02-13 15:14:58 -0500
commita7daf3da4e9f68aae4bb753e5bba93557f6819fa (patch)
tree2a4baced99c3e260ad9447d0704fbe9c7e8c8c2f /drivers/net/wireless
parent64fbb561fcbf18e24ef2a509bde3d939f25fdda3 (diff)
rt2800pci: fix spurious interrupts generation
BugLink: http://bugs.launchpad.net/bugs/922799 commit dfd00c4c8f3dfa1fd7cec45f83d98b2a49743dcd upstream. 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> 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> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/net/wireless')
-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 55cd3e1f75b..dab7dc16a6c 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -426,7 +426,6 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
426static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, 426static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
427 enum dev_state state) 427 enum dev_state state)
428{ 428{
429 int mask = (state == STATE_RADIO_IRQ_ON);
430 u32 reg; 429 u32 reg;
431 unsigned long flags; 430 unsigned long flags;
432 431
@@ -448,25 +447,14 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
448 } 447 }
449 448
450 spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); 449 spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
451 rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg); 450 reg = 0;
452 rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0); 451 if (state == STATE_RADIO_IRQ_ON) {
453 rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0); 452 rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, 1);
454 rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, mask); 453 rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, 1);
455 rt2x00_set_field32(&reg, INT_MASK_CSR_AC0_DMA_DONE, 0); 454 rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, 1);
456 rt2x00_set_field32(&reg, INT_MASK_CSR_AC1_DMA_DONE, 0); 455 rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
457 rt2x00_set_field32(&reg, INT_MASK_CSR_AC2_DMA_DONE, 0); 456 rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, 1);
458 rt2x00_set_field32(&reg, INT_MASK_CSR_AC3_DMA_DONE, 0); 457 }
459 rt2x00_set_field32(&reg, INT_MASK_CSR_HCCA_DMA_DONE, 0);
460 rt2x00_set_field32(&reg, INT_MASK_CSR_MGMT_DMA_DONE, 0);
461 rt2x00_set_field32(&reg, INT_MASK_CSR_MCU_COMMAND, 0);
462 rt2x00_set_field32(&reg, INT_MASK_CSR_RXTX_COHERENT, 0);
463 rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, mask);
464 rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, mask);
465 rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, mask);
466 rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, mask);
467 rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, 0);
468 rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
469 rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
470 rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); 458 rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
471 spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); 459 spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
472 460