aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2800pci.c
diff options
context:
space:
mode:
authorHelmut Schaa <helmut.schaa@googlemail.com>2010-07-11 12:26:48 +0200
committerJohn W. Linville <linville@tuxdriver.com>2010-07-12 16:05:34 -0400
commit78e256c9a3717bcae2e9ed05c9ec7bed7bf2c55d (patch)
tree343bf5127f29e0490616a32c4c785b7d33f3d788 /drivers/net/wireless/rt2x00/rt2800pci.c
parent50e888eae23dc062cb52a7538e85a5960ce1d91c (diff)
downloadkernel_samsung_crespo-78e256c9a3717bcae2e9ed05c9ec7bed7bf2c55d.zip
kernel_samsung_crespo-78e256c9a3717bcae2e9ed05c9ec7bed7bf2c55d.tar.gz
kernel_samsung_crespo-78e256c9a3717bcae2e9ed05c9ec7bed7bf2c55d.tar.bz2
rt2x00: Convert rt2x00 to use threaded interrupts
Use threaded interrupts for all rt2x00 PCI devices. This has several generic advantages: - Reduce the time we spend in hard irq context - Use non-atmic mac80211 functions for rx/tx Furthermore implementing broad- and multicast buffering will be much easier in process context while maintaining low latency and updating the beacon just before transmission (pre tbtt interrupt) can also be done in process context. Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2800pci.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c50
1 files changed, 37 insertions, 13 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index a9eca99..f21b77c 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -422,7 +422,8 @@ static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
- int mask = (state == STATE_RADIO_IRQ_ON);
+ int mask = (state == STATE_RADIO_IRQ_ON) ||
+ (state == STATE_RADIO_IRQ_ON_ISR);
u32 reg;
/*
@@ -631,7 +632,9 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
rt2800pci_toggle_rx(rt2x00dev, state);
break;
case STATE_RADIO_IRQ_ON:
+ case STATE_RADIO_IRQ_ON_ISR:
case STATE_RADIO_IRQ_OFF:
+ case STATE_RADIO_IRQ_OFF_ISR:
rt2800pci_toggle_irq(rt2x00dev, state);
break;
case STATE_DEEP_SLEEP:
@@ -929,20 +932,10 @@ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev)
rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
}
-static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
+static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance)
{
struct rt2x00_dev *rt2x00dev = dev_instance;
- u32 reg;
-
- /* Read status and ACK all interrupts */
- rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
- rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
-
- if (!reg)
- return IRQ_NONE;
-
- if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
- return IRQ_HANDLED;
+ u32 reg = rt2x00dev->irqvalue[0];
/*
* 1 - Rx ring done interrupt.
@@ -962,9 +955,39 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
rt2800pci_wakeup(rt2x00dev);
+ /* Enable interrupts again. */
+ rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+ STATE_RADIO_IRQ_ON_ISR);
+
return IRQ_HANDLED;
}
+static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
+{
+ struct rt2x00_dev *rt2x00dev = dev_instance;
+ u32 reg;
+
+ /* Read status and ACK all interrupts */
+ rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+
+ if (!reg)
+ return IRQ_NONE;
+
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ return IRQ_HANDLED;
+
+ /* Store irqvalue for use in the interrupt thread. */
+ rt2x00dev->irqvalue[0] = reg;
+
+ /* Disable interrupts, will be enabled again in the interrupt thread. */
+ rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+ STATE_RADIO_IRQ_OFF_ISR);
+
+
+ return IRQ_WAKE_THREAD;
+}
+
/*
* Device probe functions.
*/
@@ -1049,6 +1072,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.irq_handler = rt2800pci_interrupt,
+ .irq_handler_thread = rt2800pci_interrupt_thread,
.probe_hw = rt2800pci_probe_hw,
.get_firmware_name = rt2800pci_get_firmware_name,
.check_firmware = rt2800pci_check_firmware,