aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2400pci.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/rt2400pci.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/rt2400pci.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c54
1 files changed, 38 insertions, 16 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 25e9dcf65c4e..116244b72371 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -879,7 +879,8 @@ static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
879static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, 879static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
880 enum dev_state state) 880 enum dev_state state)
881{ 881{
882 int mask = (state == STATE_RADIO_IRQ_OFF); 882 int mask = (state == STATE_RADIO_IRQ_OFF) ||
883 (state == STATE_RADIO_IRQ_OFF_ISR);
883 u32 reg; 884 u32 reg;
884 885
885 /* 886 /*
@@ -980,7 +981,9 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
980 rt2400pci_toggle_rx(rt2x00dev, state); 981 rt2400pci_toggle_rx(rt2x00dev, state);
981 break; 982 break;
982 case STATE_RADIO_IRQ_ON: 983 case STATE_RADIO_IRQ_ON:
984 case STATE_RADIO_IRQ_ON_ISR:
983 case STATE_RADIO_IRQ_OFF: 985 case STATE_RADIO_IRQ_OFF:
986 case STATE_RADIO_IRQ_OFF_ISR:
984 rt2400pci_toggle_irq(rt2x00dev, state); 987 rt2400pci_toggle_irq(rt2x00dev, state);
985 break; 988 break;
986 case STATE_DEEP_SLEEP: 989 case STATE_DEEP_SLEEP:
@@ -1235,23 +1238,10 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
1235 } 1238 }
1236} 1239}
1237 1240
1238static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) 1241static irqreturn_t rt2400pci_interrupt_thread(int irq, void *dev_instance)
1239{ 1242{
1240 struct rt2x00_dev *rt2x00dev = dev_instance; 1243 struct rt2x00_dev *rt2x00dev = dev_instance;
1241 u32 reg; 1244 u32 reg = rt2x00dev->irqvalue[0];
1242
1243 /*
1244 * Get the interrupt sources & saved to local variable.
1245 * Write register value back to clear pending interrupts.
1246 */
1247 rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
1248 rt2x00pci_register_write(rt2x00dev, CSR7, reg);
1249
1250 if (!reg)
1251 return IRQ_NONE;
1252
1253 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
1254 return IRQ_HANDLED;
1255 1245
1256 /* 1246 /*
1257 * Handle interrupts, walk through all bits 1247 * Handle interrupts, walk through all bits
@@ -1289,9 +1279,40 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
1289 if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) 1279 if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
1290 rt2400pci_txdone(rt2x00dev, QID_AC_BK); 1280 rt2400pci_txdone(rt2x00dev, QID_AC_BK);
1291 1281
1282 /* Enable interrupts again. */
1283 rt2x00dev->ops->lib->set_device_state(rt2x00dev,
1284 STATE_RADIO_IRQ_ON_ISR);
1292 return IRQ_HANDLED; 1285 return IRQ_HANDLED;
1293} 1286}
1294 1287
1288static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
1289{
1290 struct rt2x00_dev *rt2x00dev = dev_instance;
1291 u32 reg;
1292
1293 /*
1294 * Get the interrupt sources & saved to local variable.
1295 * Write register value back to clear pending interrupts.
1296 */
1297 rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
1298 rt2x00pci_register_write(rt2x00dev, CSR7, reg);
1299
1300 if (!reg)
1301 return IRQ_NONE;
1302
1303 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
1304 return IRQ_HANDLED;
1305
1306 /* Store irqvalues for use in the interrupt thread. */
1307 rt2x00dev->irqvalue[0] = reg;
1308
1309 /* Disable interrupts, will be enabled again in the interrupt thread. */
1310 rt2x00dev->ops->lib->set_device_state(rt2x00dev,
1311 STATE_RADIO_IRQ_OFF_ISR);
1312
1313 return IRQ_WAKE_THREAD;
1314}
1315
1295/* 1316/*
1296 * Device probe functions. 1317 * Device probe functions.
1297 */ 1318 */
@@ -1581,6 +1602,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
1581 1602
1582static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { 1603static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
1583 .irq_handler = rt2400pci_interrupt, 1604 .irq_handler = rt2400pci_interrupt,
1605 .irq_handler_thread = rt2400pci_interrupt_thread,
1584 .probe_hw = rt2400pci_probe_hw, 1606 .probe_hw = rt2400pci_probe_hw,
1585 .initialize = rt2x00pci_initialize, 1607 .initialize = rt2x00pci_initialize,
1586 .uninitialize = rt2x00pci_uninitialize, 1608 .uninitialize = rt2x00pci_uninitialize,