aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt61pci.c
diff options
context:
space:
mode:
authorHelmut Schaa <helmut.schaa@googlemail.com>2010-07-11 06:26:48 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-07-12 16:05:34 -0400
commit78e256c9a3717bcae2e9ed05c9ec7bed7bf2c55d (patch)
tree343bf5127f29e0490616a32c4c785b7d33f3d788 /drivers/net/wireless/rt2x00/rt61pci.c
parent50e888eae23dc062cb52a7538e85a5960ce1d91c (diff)
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/rt61pci.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c64
1 files changed, 44 insertions, 20 deletions
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index fe7bce7c05de..049433fa760d 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1622,7 +1622,8 @@ static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
1622static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, 1622static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
1623 enum dev_state state) 1623 enum dev_state state)
1624{ 1624{
1625 int mask = (state == STATE_RADIO_IRQ_OFF); 1625 int mask = (state == STATE_RADIO_IRQ_OFF) ||
1626 (state == STATE_RADIO_IRQ_OFF_ISR);
1626 u32 reg; 1627 u32 reg;
1627 1628
1628 /* 1629 /*
@@ -1739,7 +1740,9 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
1739 rt61pci_toggle_rx(rt2x00dev, state); 1740 rt61pci_toggle_rx(rt2x00dev, state);
1740 break; 1741 break;
1741 case STATE_RADIO_IRQ_ON: 1742 case STATE_RADIO_IRQ_ON:
1743 case STATE_RADIO_IRQ_ON_ISR:
1742 case STATE_RADIO_IRQ_OFF: 1744 case STATE_RADIO_IRQ_OFF:
1745 case STATE_RADIO_IRQ_OFF_ISR:
1743 rt61pci_toggle_irq(rt2x00dev, state); 1746 rt61pci_toggle_irq(rt2x00dev, state);
1744 break; 1747 break;
1745 case STATE_DEEP_SLEEP: 1748 case STATE_DEEP_SLEEP:
@@ -2147,27 +2150,11 @@ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)
2147 rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); 2150 rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
2148} 2151}
2149 2152
2150static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) 2153static irqreturn_t rt61pci_interrupt_thread(int irq, void *dev_instance)
2151{ 2154{
2152 struct rt2x00_dev *rt2x00dev = dev_instance; 2155 struct rt2x00_dev *rt2x00dev = dev_instance;
2153 u32 reg_mcu; 2156 u32 reg = rt2x00dev->irqvalue[0];
2154 u32 reg; 2157 u32 reg_mcu = rt2x00dev->irqvalue[1];
2155
2156 /*
2157 * Get the interrupt sources & saved to local variable.
2158 * Write register value back to clear pending interrupts.
2159 */
2160 rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg_mcu);
2161 rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu);
2162
2163 rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
2164 rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
2165
2166 if (!reg && !reg_mcu)
2167 return IRQ_NONE;
2168
2169 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
2170 return IRQ_HANDLED;
2171 2158
2172 /* 2159 /*
2173 * Handle interrupts, walk through all bits 2160 * Handle interrupts, walk through all bits
@@ -2206,9 +2193,45 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
2206 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE)) 2193 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE))
2207 rt2x00lib_beacondone(rt2x00dev); 2194 rt2x00lib_beacondone(rt2x00dev);
2208 2195
2196 /* Enable interrupts again. */
2197 rt2x00dev->ops->lib->set_device_state(rt2x00dev,
2198 STATE_RADIO_IRQ_ON_ISR);
2209 return IRQ_HANDLED; 2199 return IRQ_HANDLED;
2210} 2200}
2211 2201
2202
2203static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
2204{
2205 struct rt2x00_dev *rt2x00dev = dev_instance;
2206 u32 reg_mcu;
2207 u32 reg;
2208
2209 /*
2210 * Get the interrupt sources & saved to local variable.
2211 * Write register value back to clear pending interrupts.
2212 */
2213 rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg_mcu);
2214 rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu);
2215
2216 rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
2217 rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
2218
2219 if (!reg && !reg_mcu)
2220 return IRQ_NONE;
2221
2222 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
2223 return IRQ_HANDLED;
2224
2225 /* Store irqvalues for use in the interrupt thread. */
2226 rt2x00dev->irqvalue[0] = reg;
2227 rt2x00dev->irqvalue[1] = reg_mcu;
2228
2229 /* Disable interrupts, will be enabled again in the interrupt thread. */
2230 rt2x00dev->ops->lib->set_device_state(rt2x00dev,
2231 STATE_RADIO_IRQ_OFF_ISR);
2232 return IRQ_WAKE_THREAD;
2233}
2234
2212/* 2235/*
2213 * Device probe functions. 2236 * Device probe functions.
2214 */ 2237 */
@@ -2795,6 +2818,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
2795 2818
2796static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { 2819static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
2797 .irq_handler = rt61pci_interrupt, 2820 .irq_handler = rt61pci_interrupt,
2821 .irq_handler_thread = rt61pci_interrupt_thread,
2798 .probe_hw = rt61pci_probe_hw, 2822 .probe_hw = rt61pci_probe_hw,
2799 .get_firmware_name = rt61pci_get_firmware_name, 2823 .get_firmware_name = rt61pci_get_firmware_name,
2800 .check_firmware = rt61pci_check_firmware, 2824 .check_firmware = rt61pci_check_firmware,