aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
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
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')
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c54
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c55
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c50
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h11
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c23
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00reg.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c64
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c2
11 files changed, 201 insertions, 70 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,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index faa804cf181a..5e80948d1a3e 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1033,7 +1033,8 @@ static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
1033static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, 1033static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
1034 enum dev_state state) 1034 enum dev_state state)
1035{ 1035{
1036 int mask = (state == STATE_RADIO_IRQ_OFF); 1036 int mask = (state == STATE_RADIO_IRQ_OFF) ||
1037 (state == STATE_RADIO_IRQ_OFF_ISR);
1037 u32 reg; 1038 u32 reg;
1038 1039
1039 /* 1040 /*
@@ -1134,7 +1135,9 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
1134 rt2500pci_toggle_rx(rt2x00dev, state); 1135 rt2500pci_toggle_rx(rt2x00dev, state);
1135 break; 1136 break;
1136 case STATE_RADIO_IRQ_ON: 1137 case STATE_RADIO_IRQ_ON:
1138 case STATE_RADIO_IRQ_ON_ISR:
1137 case STATE_RADIO_IRQ_OFF: 1139 case STATE_RADIO_IRQ_OFF:
1140 case STATE_RADIO_IRQ_OFF_ISR:
1138 rt2500pci_toggle_irq(rt2x00dev, state); 1141 rt2500pci_toggle_irq(rt2x00dev, state);
1139 break; 1142 break;
1140 case STATE_DEEP_SLEEP: 1143 case STATE_DEEP_SLEEP:
@@ -1367,23 +1370,10 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
1367 } 1370 }
1368} 1371}
1369 1372
1370static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) 1373static irqreturn_t rt2500pci_interrupt_thread(int irq, void *dev_instance)
1371{ 1374{
1372 struct rt2x00_dev *rt2x00dev = dev_instance; 1375 struct rt2x00_dev *rt2x00dev = dev_instance;
1373 u32 reg; 1376 u32 reg = rt2x00dev->irqvalue[0];
1374
1375 /*
1376 * Get the interrupt sources & saved to local variable.
1377 * Write register value back to clear pending interrupts.
1378 */
1379 rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
1380 rt2x00pci_register_write(rt2x00dev, CSR7, reg);
1381
1382 if (!reg)
1383 return IRQ_NONE;
1384
1385 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
1386 return IRQ_HANDLED;
1387 1377
1388 /* 1378 /*
1389 * Handle interrupts, walk through all bits 1379 * Handle interrupts, walk through all bits
@@ -1421,9 +1411,41 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
1421 if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) 1411 if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
1422 rt2500pci_txdone(rt2x00dev, QID_AC_BK); 1412 rt2500pci_txdone(rt2x00dev, QID_AC_BK);
1423 1413
1414 /* Enable interrupts again. */
1415 rt2x00dev->ops->lib->set_device_state(rt2x00dev,
1416 STATE_RADIO_IRQ_ON_ISR);
1417
1424 return IRQ_HANDLED; 1418 return IRQ_HANDLED;
1425} 1419}
1426 1420
1421static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
1422{
1423 struct rt2x00_dev *rt2x00dev = dev_instance;
1424 u32 reg;
1425
1426 /*
1427 * Get the interrupt sources & saved to local variable.
1428 * Write register value back to clear pending interrupts.
1429 */
1430 rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
1431 rt2x00pci_register_write(rt2x00dev, CSR7, reg);
1432
1433 if (!reg)
1434 return IRQ_NONE;
1435
1436 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
1437 return IRQ_HANDLED;
1438
1439 /* Store irqvalues for use in the interrupt thread. */
1440 rt2x00dev->irqvalue[0] = reg;
1441
1442 /* Disable interrupts, will be enabled again in the interrupt thread. */
1443 rt2x00dev->ops->lib->set_device_state(rt2x00dev,
1444 STATE_RADIO_IRQ_OFF_ISR);
1445
1446 return IRQ_WAKE_THREAD;
1447}
1448
1427/* 1449/*
1428 * Device probe functions. 1450 * Device probe functions.
1429 */ 1451 */
@@ -1874,6 +1896,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
1874 1896
1875static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { 1897static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
1876 .irq_handler = rt2500pci_interrupt, 1898 .irq_handler = rt2500pci_interrupt,
1899 .irq_handler_thread = rt2500pci_interrupt_thread,
1877 .probe_hw = rt2500pci_probe_hw, 1900 .probe_hw = rt2500pci_probe_hw,
1878 .initialize = rt2x00pci_initialize, 1901 .initialize = rt2x00pci_initialize,
1879 .uninitialize = rt2x00pci_uninitialize, 1902 .uninitialize = rt2x00pci_uninitialize,
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 009323e6c20f..242d59558b79 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1004,7 +1004,9 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
1004 rt2500usb_toggle_rx(rt2x00dev, state); 1004 rt2500usb_toggle_rx(rt2x00dev, state);
1005 break; 1005 break;
1006 case STATE_RADIO_IRQ_ON: 1006 case STATE_RADIO_IRQ_ON:
1007 case STATE_RADIO_IRQ_ON_ISR:
1007 case STATE_RADIO_IRQ_OFF: 1008 case STATE_RADIO_IRQ_OFF:
1009 case STATE_RADIO_IRQ_OFF_ISR:
1008 /* No support, but no error either */ 1010 /* No support, but no error either */
1009 break; 1011 break;
1010 case STATE_DEEP_SLEEP: 1012 case STATE_DEEP_SLEEP:
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index a9eca99d416c..f21b77c61ad4 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,
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); 425 int mask = (state == STATE_RADIO_IRQ_ON) ||
426 (state == STATE_RADIO_IRQ_ON_ISR);
426 u32 reg; 427 u32 reg;
427 428
428 /* 429 /*
@@ -631,7 +632,9 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
631 rt2800pci_toggle_rx(rt2x00dev, state); 632 rt2800pci_toggle_rx(rt2x00dev, state);
632 break; 633 break;
633 case STATE_RADIO_IRQ_ON: 634 case STATE_RADIO_IRQ_ON:
635 case STATE_RADIO_IRQ_ON_ISR:
634 case STATE_RADIO_IRQ_OFF: 636 case STATE_RADIO_IRQ_OFF:
637 case STATE_RADIO_IRQ_OFF_ISR:
635 rt2800pci_toggle_irq(rt2x00dev, state); 638 rt2800pci_toggle_irq(rt2x00dev, state);
636 break; 639 break;
637 case STATE_DEEP_SLEEP: 640 case STATE_DEEP_SLEEP:
@@ -929,20 +932,10 @@ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev)
929 rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); 932 rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
930} 933}
931 934
932static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) 935static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance)
933{ 936{
934 struct rt2x00_dev *rt2x00dev = dev_instance; 937 struct rt2x00_dev *rt2x00dev = dev_instance;
935 u32 reg; 938 u32 reg = rt2x00dev->irqvalue[0];
936
937 /* Read status and ACK all interrupts */
938 rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
939 rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
940
941 if (!reg)
942 return IRQ_NONE;
943
944 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
945 return IRQ_HANDLED;
946 939
947 /* 940 /*
948 * 1 - Rx ring done interrupt. 941 * 1 - Rx ring done interrupt.
@@ -962,9 +955,39 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
962 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) 955 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
963 rt2800pci_wakeup(rt2x00dev); 956 rt2800pci_wakeup(rt2x00dev);
964 957
958 /* Enable interrupts again. */
959 rt2x00dev->ops->lib->set_device_state(rt2x00dev,
960 STATE_RADIO_IRQ_ON_ISR);
961
965 return IRQ_HANDLED; 962 return IRQ_HANDLED;
966} 963}
967 964
965static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
966{
967 struct rt2x00_dev *rt2x00dev = dev_instance;
968 u32 reg;
969
970 /* Read status and ACK all interrupts */
971 rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
972 rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
973
974 if (!reg)
975 return IRQ_NONE;
976
977 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
978 return IRQ_HANDLED;
979
980 /* Store irqvalue for use in the interrupt thread. */
981 rt2x00dev->irqvalue[0] = reg;
982
983 /* Disable interrupts, will be enabled again in the interrupt thread. */
984 rt2x00dev->ops->lib->set_device_state(rt2x00dev,
985 STATE_RADIO_IRQ_OFF_ISR);
986
987
988 return IRQ_WAKE_THREAD;
989}
990
968/* 991/*
969 * Device probe functions. 992 * Device probe functions.
970 */ 993 */
@@ -1049,6 +1072,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
1049 1072
1050static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { 1073static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
1051 .irq_handler = rt2800pci_interrupt, 1074 .irq_handler = rt2800pci_interrupt,
1075 .irq_handler_thread = rt2800pci_interrupt_thread,
1052 .probe_hw = rt2800pci_probe_hw, 1076 .probe_hw = rt2800pci_probe_hw,
1053 .get_firmware_name = rt2800pci_get_firmware_name, 1077 .get_firmware_name = rt2800pci_get_firmware_name,
1054 .check_firmware = rt2800pci_check_firmware, 1078 .check_firmware = rt2800pci_check_firmware,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 5aa7563155cd..df78e28526bf 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -406,7 +406,9 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
406 rt2800usb_toggle_rx(rt2x00dev, state); 406 rt2800usb_toggle_rx(rt2x00dev, state);
407 break; 407 break;
408 case STATE_RADIO_IRQ_ON: 408 case STATE_RADIO_IRQ_ON:
409 case STATE_RADIO_IRQ_ON_ISR:
409 case STATE_RADIO_IRQ_OFF: 410 case STATE_RADIO_IRQ_OFF:
411 case STATE_RADIO_IRQ_OFF_ISR:
410 /* No support, but no error either */ 412 /* No support, but no error either */
411 break; 413 break;
412 case STATE_DEEP_SLEEP: 414 case STATE_DEEP_SLEEP:
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 97b6261fee4f..0fa21410676f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -515,6 +515,11 @@ struct rt2x00lib_ops {
515 irq_handler_t irq_handler; 515 irq_handler_t irq_handler;
516 516
517 /* 517 /*
518 * Threaded Interrupt handlers.
519 */
520 irq_handler_t irq_handler_thread;
521
522 /*
518 * Device init handlers. 523 * Device init handlers.
519 */ 524 */
520 int (*probe_hw) (struct rt2x00_dev *rt2x00dev); 525 int (*probe_hw) (struct rt2x00_dev *rt2x00dev);
@@ -871,6 +876,12 @@ struct rt2x00_dev {
871 const struct firmware *fw; 876 const struct firmware *fw;
872 877
873 /* 878 /*
879 * Interrupt values, stored between interrupt service routine
880 * and interrupt thread routine.
881 */
882 u32 irqvalue[2];
883
884 /*
874 * Driver specific data. 885 * Driver specific data.
875 */ 886 */
876 void *priv; 887 void *priv;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 0906e14b347f..d3ebb4144562 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -340,9 +340,17 @@ void rt2x00lib_txdone(struct queue_entry *entry,
340 * send the status report back. 340 * send the status report back.
341 */ 341 */
342 if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) 342 if (!(skbdesc_flags & SKBDESC_NOT_MAC80211))
343 ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); 343 /*
344 * Only PCI and SOC devices process the tx status in process
345 * context. Hence use ieee80211_tx_status for PCI and SOC
346 * devices and stick to ieee80211_tx_status_irqsafe for USB.
347 */
348 if (rt2x00_is_usb(rt2x00dev))
349 ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb);
350 else
351 ieee80211_tx_status(rt2x00dev->hw, entry->skb);
344 else 352 else
345 dev_kfree_skb_irq(entry->skb); 353 dev_kfree_skb_any(entry->skb);
346 354
347 /* 355 /*
348 * Make this entry available for reuse. 356 * Make this entry available for reuse.
@@ -489,7 +497,16 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
489 */ 497 */
490 rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); 498 rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
491 memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status)); 499 memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status));
492 ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb); 500
501 /*
502 * Currently only PCI and SOC devices handle rx interrupts in process
503 * context. Hence, use ieee80211_rx_irqsafe for USB and ieee80211_rx_ni
504 * for PCI and SOC devices.
505 */
506 if (rt2x00_is_usb(rt2x00dev))
507 ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb);
508 else
509 ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
493 510
494 /* 511 /*
495 * Replace the skb with the freshly allocated one. 512 * Replace the skb with the freshly allocated one.
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index fc9da8358784..19b262e1ddbe 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -153,8 +153,10 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
153 /* 153 /*
154 * Register interrupt handler. 154 * Register interrupt handler.
155 */ 155 */
156 status = request_irq(rt2x00dev->irq, rt2x00dev->ops->lib->irq_handler, 156 status = request_threaded_irq(rt2x00dev->irq,
157 IRQF_SHARED, rt2x00dev->name, rt2x00dev); 157 rt2x00dev->ops->lib->irq_handler,
158 rt2x00dev->ops->lib->irq_handler_thread,
159 IRQF_SHARED, rt2x00dev->name, rt2x00dev);
158 if (status) { 160 if (status) {
159 ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", 161 ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
160 rt2x00dev->irq, status); 162 rt2x00dev->irq, status);
diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
index b9fe94873ee0..055501c355a5 100644
--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
+++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
@@ -88,6 +88,8 @@ enum dev_state {
88 STATE_RADIO_RX_OFF_LINK, 88 STATE_RADIO_RX_OFF_LINK,
89 STATE_RADIO_IRQ_ON, 89 STATE_RADIO_IRQ_ON,
90 STATE_RADIO_IRQ_OFF, 90 STATE_RADIO_IRQ_OFF,
91 STATE_RADIO_IRQ_ON_ISR,
92 STATE_RADIO_IRQ_OFF_ISR,
91}; 93};
92 94
93/* 95/*
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,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index cad07b69c53e..aa9de18fd410 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1400,7 +1400,9 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
1400 rt73usb_toggle_rx(rt2x00dev, state); 1400 rt73usb_toggle_rx(rt2x00dev, state);
1401 break; 1401 break;
1402 case STATE_RADIO_IRQ_ON: 1402 case STATE_RADIO_IRQ_ON:
1403 case STATE_RADIO_IRQ_ON_ISR:
1403 case STATE_RADIO_IRQ_OFF: 1404 case STATE_RADIO_IRQ_OFF:
1405 case STATE_RADIO_IRQ_OFF_ISR:
1404 /* No support, but no error either */ 1406 /* No support, but no error either */
1405 break; 1407 break;
1406 case STATE_DEEP_SLEEP: 1408 case STATE_DEEP_SLEEP: