aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIdo Yariv <ido@wizery.com>2011-03-01 08:14:41 -0500
committerLuciano Coelho <coelho@ti.com>2011-03-03 09:10:46 -0500
commita620865edf62ea2d024bbfe62162244473badfcb (patch)
tree5eb75c0c194cba0e40fa9dc9b6bd01cadff83bf9
parent393fb560d328cc06e6a5c7b7473901ad724f82e7 (diff)
wl12xx: Switch to a threaded interrupt handler
To achieve maximal throughput, it is very important to react to interrupts as soon as possible. Currently the interrupt handler wakes up a worker for handling interrupts in process context. A cleaner and more efficient design would be to request a threaded interrupt handler. This handler's priority is very high, and can do blocking operations such as SDIO/SPI transactions. Some work can be deferred, mostly calls to mac80211 APIs (ieee80211_rx_ni and ieee80211_tx_status). By deferring such work to a different worker, we can keep the irq handler thread more I/O responsive. In addition, on multi-core systems the two threads can be scheduled on different cores, which will improve overall performance. The use of WL1271_FLAG_IRQ_PENDING & WL1271_FLAG_IRQ_RUNNING was changed. For simplicity, always query the FW for more pending interrupts. Since there are relatively long bursts of interrupts, the extra FW status read overhead is negligible. In addition, this enables registering the IRQ handler with the ONESHOT option. Signed-off-by: Ido Yariv <ido@wizery.com> Reviewed-by: Luciano Coelho <coelho@ti.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
-rw-r--r--drivers/net/wireless/wl12xx/debugfs.c2
-rw-r--r--drivers/net/wireless/wl12xx/io.h1
-rw-r--r--drivers/net/wireless/wl12xx/main.c127
-rw-r--r--drivers/net/wireless/wl12xx/ps.c6
-rw-r--r--drivers/net/wireless/wl12xx/ps.h2
-rw-r--r--drivers/net/wireless/wl12xx/rx.c3
-rw-r--r--drivers/net/wireless/wl12xx/sdio.c16
-rw-r--r--drivers/net/wireless/wl12xx/spi.c19
-rw-r--r--drivers/net/wireless/wl12xx/tx.c5
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h13
10 files changed, 113 insertions, 81 deletions
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index bebfa28a171a..8e75b09723b9 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -99,7 +99,7 @@ static void wl1271_debugfs_update_stats(struct wl1271 *wl)
99 99
100 mutex_lock(&wl->mutex); 100 mutex_lock(&wl->mutex);
101 101
102 ret = wl1271_ps_elp_wakeup(wl, false); 102 ret = wl1271_ps_elp_wakeup(wl);
103 if (ret < 0) 103 if (ret < 0)
104 goto out; 104 goto out;
105 105
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
index 844b32b170bb..c1aac8292089 100644
--- a/drivers/net/wireless/wl12xx/io.h
+++ b/drivers/net/wireless/wl12xx/io.h
@@ -168,5 +168,6 @@ void wl1271_unregister_hw(struct wl1271 *wl);
168int wl1271_init_ieee80211(struct wl1271 *wl); 168int wl1271_init_ieee80211(struct wl1271 *wl);
169struct ieee80211_hw *wl1271_alloc_hw(void); 169struct ieee80211_hw *wl1271_alloc_hw(void);
170int wl1271_free_hw(struct wl1271 *wl); 170int wl1271_free_hw(struct wl1271 *wl);
171irqreturn_t wl1271_irq(int irq, void *data);
171 172
172#endif 173#endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index ba34ac3a440d..f408c5a84cc9 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -374,7 +374,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
374 if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) 374 if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
375 goto out; 375 goto out;
376 376
377 ret = wl1271_ps_elp_wakeup(wl, false); 377 ret = wl1271_ps_elp_wakeup(wl);
378 if (ret < 0) 378 if (ret < 0)
379 goto out; 379 goto out;
380 380
@@ -635,16 +635,39 @@ static void wl1271_fw_status(struct wl1271 *wl,
635 (s64)le32_to_cpu(status->fw_localtime); 635 (s64)le32_to_cpu(status->fw_localtime);
636} 636}
637 637
638#define WL1271_IRQ_MAX_LOOPS 10 638static void wl1271_flush_deferred_work(struct wl1271 *wl)
639{
640 struct sk_buff *skb;
641
642 /* Pass all received frames to the network stack */
643 while ((skb = skb_dequeue(&wl->deferred_rx_queue)))
644 ieee80211_rx_ni(wl->hw, skb);
645
646 /* Return sent skbs to the network stack */
647 while ((skb = skb_dequeue(&wl->deferred_tx_queue)))
648 ieee80211_tx_status(wl->hw, skb);
649}
650
651static void wl1271_netstack_work(struct work_struct *work)
652{
653 struct wl1271 *wl =
654 container_of(work, struct wl1271, netstack_work);
655
656 do {
657 wl1271_flush_deferred_work(wl);
658 } while (skb_queue_len(&wl->deferred_rx_queue));
659}
639 660
640static void wl1271_irq_work(struct work_struct *work) 661#define WL1271_IRQ_MAX_LOOPS 256
662
663irqreturn_t wl1271_irq(int irq, void *cookie)
641{ 664{
642 int ret; 665 int ret;
643 u32 intr; 666 u32 intr;
644 int loopcount = WL1271_IRQ_MAX_LOOPS; 667 int loopcount = WL1271_IRQ_MAX_LOOPS;
645 unsigned long flags; 668 struct wl1271 *wl = (struct wl1271 *)cookie;
646 struct wl1271 *wl = 669 bool done = false;
647 container_of(work, struct wl1271, irq_work); 670 unsigned int defer_count;
648 671
649 mutex_lock(&wl->mutex); 672 mutex_lock(&wl->mutex);
650 673
@@ -653,26 +676,27 @@ static void wl1271_irq_work(struct work_struct *work)
653 if (unlikely(wl->state == WL1271_STATE_OFF)) 676 if (unlikely(wl->state == WL1271_STATE_OFF))
654 goto out; 677 goto out;
655 678
656 ret = wl1271_ps_elp_wakeup(wl, true); 679 ret = wl1271_ps_elp_wakeup(wl);
657 if (ret < 0) 680 if (ret < 0)
658 goto out; 681 goto out;
659 682
660 spin_lock_irqsave(&wl->wl_lock, flags); 683 while (!done && loopcount--) {
661 while (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags) && loopcount) { 684 /*
662 clear_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags); 685 * In order to avoid a race with the hardirq, clear the flag
663 spin_unlock_irqrestore(&wl->wl_lock, flags); 686 * before acknowledging the chip. Since the mutex is held,
664 loopcount--; 687 * wl1271_ps_elp_wakeup cannot be called concurrently.
688 */
689 clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
690 smp_mb__after_clear_bit();
665 691
666 wl1271_fw_status(wl, wl->fw_status); 692 wl1271_fw_status(wl, wl->fw_status);
667 intr = le32_to_cpu(wl->fw_status->common.intr); 693 intr = le32_to_cpu(wl->fw_status->common.intr);
694 intr &= WL1271_INTR_MASK;
668 if (!intr) { 695 if (!intr) {
669 wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); 696 done = true;
670 spin_lock_irqsave(&wl->wl_lock, flags);
671 continue; 697 continue;
672 } 698 }
673 699
674 intr &= WL1271_INTR_MASK;
675
676 if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { 700 if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) {
677 wl1271_error("watchdog interrupt received! " 701 wl1271_error("watchdog interrupt received! "
678 "starting recovery."); 702 "starting recovery.");
@@ -682,7 +706,7 @@ static void wl1271_irq_work(struct work_struct *work)
682 goto out; 706 goto out;
683 } 707 }
684 708
685 if (intr & WL1271_ACX_INTR_DATA) { 709 if (likely(intr & WL1271_ACX_INTR_DATA)) {
686 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); 710 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
687 711
688 wl1271_rx(wl, &wl->fw_status->common); 712 wl1271_rx(wl, &wl->fw_status->common);
@@ -701,6 +725,12 @@ static void wl1271_irq_work(struct work_struct *work)
701 if (wl->fw_status->common.tx_results_counter != 725 if (wl->fw_status->common.tx_results_counter !=
702 (wl->tx_results_count & 0xff)) 726 (wl->tx_results_count & 0xff))
703 wl1271_tx_complete(wl); 727 wl1271_tx_complete(wl);
728
729 /* Make sure the deferred queues don't get too long */
730 defer_count = skb_queue_len(&wl->deferred_tx_queue) +
731 skb_queue_len(&wl->deferred_rx_queue);
732 if (defer_count > WL1271_DEFERRED_QUEUE_LIMIT)
733 wl1271_flush_deferred_work(wl);
704 } 734 }
705 735
706 if (intr & WL1271_ACX_INTR_EVENT_A) { 736 if (intr & WL1271_ACX_INTR_EVENT_A) {
@@ -719,21 +749,16 @@ static void wl1271_irq_work(struct work_struct *work)
719 749
720 if (intr & WL1271_ACX_INTR_HW_AVAILABLE) 750 if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
721 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); 751 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
722
723 spin_lock_irqsave(&wl->wl_lock, flags);
724 } 752 }
725 753
726 if (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags))
727 ieee80211_queue_work(wl->hw, &wl->irq_work);
728 else
729 clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
730 spin_unlock_irqrestore(&wl->wl_lock, flags);
731
732 wl1271_ps_elp_sleep(wl); 754 wl1271_ps_elp_sleep(wl);
733 755
734out: 756out:
735 mutex_unlock(&wl->mutex); 757 mutex_unlock(&wl->mutex);
758
759 return IRQ_HANDLED;
736} 760}
761EXPORT_SYMBOL_GPL(wl1271_irq);
737 762
738static int wl1271_fetch_firmware(struct wl1271 *wl) 763static int wl1271_fetch_firmware(struct wl1271 *wl)
739{ 764{
@@ -974,7 +999,6 @@ int wl1271_plt_start(struct wl1271 *wl)
974 goto out; 999 goto out;
975 1000
976irq_disable: 1001irq_disable:
977 wl1271_disable_interrupts(wl);
978 mutex_unlock(&wl->mutex); 1002 mutex_unlock(&wl->mutex);
979 /* Unlocking the mutex in the middle of handling is 1003 /* Unlocking the mutex in the middle of handling is
980 inherently unsafe. In this case we deem it safe to do, 1004 inherently unsafe. In this case we deem it safe to do,
@@ -983,7 +1007,9 @@ irq_disable:
983 work function will not do anything.) Also, any other 1007 work function will not do anything.) Also, any other
984 possible concurrent operations will fail due to the 1008 possible concurrent operations will fail due to the
985 current state, hence the wl1271 struct should be safe. */ 1009 current state, hence the wl1271 struct should be safe. */
986 cancel_work_sync(&wl->irq_work); 1010 wl1271_disable_interrupts(wl);
1011 wl1271_flush_deferred_work(wl);
1012 cancel_work_sync(&wl->netstack_work);
987 mutex_lock(&wl->mutex); 1013 mutex_lock(&wl->mutex);
988power_off: 1014power_off:
989 wl1271_power_off(wl); 1015 wl1271_power_off(wl);
@@ -1010,14 +1036,15 @@ int __wl1271_plt_stop(struct wl1271 *wl)
1010 goto out; 1036 goto out;
1011 } 1037 }
1012 1038
1013 wl1271_disable_interrupts(wl);
1014 wl1271_power_off(wl); 1039 wl1271_power_off(wl);
1015 1040
1016 wl->state = WL1271_STATE_OFF; 1041 wl->state = WL1271_STATE_OFF;
1017 wl->rx_counter = 0; 1042 wl->rx_counter = 0;
1018 1043
1019 mutex_unlock(&wl->mutex); 1044 mutex_unlock(&wl->mutex);
1020 cancel_work_sync(&wl->irq_work); 1045 wl1271_disable_interrupts(wl);
1046 wl1271_flush_deferred_work(wl);
1047 cancel_work_sync(&wl->netstack_work);
1021 cancel_work_sync(&wl->recovery_work); 1048 cancel_work_sync(&wl->recovery_work);
1022 mutex_lock(&wl->mutex); 1049 mutex_lock(&wl->mutex);
1023out: 1050out:
@@ -1169,7 +1196,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
1169 break; 1196 break;
1170 1197
1171irq_disable: 1198irq_disable:
1172 wl1271_disable_interrupts(wl);
1173 mutex_unlock(&wl->mutex); 1199 mutex_unlock(&wl->mutex);
1174 /* Unlocking the mutex in the middle of handling is 1200 /* Unlocking the mutex in the middle of handling is
1175 inherently unsafe. In this case we deem it safe to do, 1201 inherently unsafe. In this case we deem it safe to do,
@@ -1178,7 +1204,9 @@ irq_disable:
1178 work function will not do anything.) Also, any other 1204 work function will not do anything.) Also, any other
1179 possible concurrent operations will fail due to the 1205 possible concurrent operations will fail due to the
1180 current state, hence the wl1271 struct should be safe. */ 1206 current state, hence the wl1271 struct should be safe. */
1181 cancel_work_sync(&wl->irq_work); 1207 wl1271_disable_interrupts(wl);
1208 wl1271_flush_deferred_work(wl);
1209 cancel_work_sync(&wl->netstack_work);
1182 mutex_lock(&wl->mutex); 1210 mutex_lock(&wl->mutex);
1183power_off: 1211power_off:
1184 wl1271_power_off(wl); 1212 wl1271_power_off(wl);
@@ -1244,12 +1272,12 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
1244 1272
1245 wl->state = WL1271_STATE_OFF; 1273 wl->state = WL1271_STATE_OFF;
1246 1274
1247 wl1271_disable_interrupts(wl);
1248
1249 mutex_unlock(&wl->mutex); 1275 mutex_unlock(&wl->mutex);
1250 1276
1277 wl1271_disable_interrupts(wl);
1278 wl1271_flush_deferred_work(wl);
1251 cancel_delayed_work_sync(&wl->scan_complete_work); 1279 cancel_delayed_work_sync(&wl->scan_complete_work);
1252 cancel_work_sync(&wl->irq_work); 1280 cancel_work_sync(&wl->netstack_work);
1253 cancel_work_sync(&wl->tx_work); 1281 cancel_work_sync(&wl->tx_work);
1254 cancel_delayed_work_sync(&wl->pspoll_work); 1282 cancel_delayed_work_sync(&wl->pspoll_work);
1255 cancel_delayed_work_sync(&wl->elp_work); 1283 cancel_delayed_work_sync(&wl->elp_work);
@@ -1525,7 +1553,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
1525 1553
1526 is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); 1554 is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
1527 1555
1528 ret = wl1271_ps_elp_wakeup(wl, false); 1556 ret = wl1271_ps_elp_wakeup(wl);
1529 if (ret < 0) 1557 if (ret < 0)
1530 goto out; 1558 goto out;
1531 1559
@@ -1681,7 +1709,7 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
1681 if (unlikely(wl->state == WL1271_STATE_OFF)) 1709 if (unlikely(wl->state == WL1271_STATE_OFF))
1682 goto out; 1710 goto out;
1683 1711
1684 ret = wl1271_ps_elp_wakeup(wl, false); 1712 ret = wl1271_ps_elp_wakeup(wl);
1685 if (ret < 0) 1713 if (ret < 0)
1686 goto out; 1714 goto out;
1687 1715
@@ -1910,7 +1938,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
1910 goto out_unlock; 1938 goto out_unlock;
1911 } 1939 }
1912 1940
1913 ret = wl1271_ps_elp_wakeup(wl, false); 1941 ret = wl1271_ps_elp_wakeup(wl);
1914 if (ret < 0) 1942 if (ret < 0)
1915 goto out_unlock; 1943 goto out_unlock;
1916 1944
@@ -2013,7 +2041,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
2013 goto out; 2041 goto out;
2014 } 2042 }
2015 2043
2016 ret = wl1271_ps_elp_wakeup(wl, false); 2044 ret = wl1271_ps_elp_wakeup(wl);
2017 if (ret < 0) 2045 if (ret < 0)
2018 goto out; 2046 goto out;
2019 2047
@@ -2039,7 +2067,7 @@ static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
2039 goto out; 2067 goto out;
2040 } 2068 }
2041 2069
2042 ret = wl1271_ps_elp_wakeup(wl, false); 2070 ret = wl1271_ps_elp_wakeup(wl);
2043 if (ret < 0) 2071 if (ret < 0)
2044 goto out; 2072 goto out;
2045 2073
@@ -2067,7 +2095,7 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
2067 goto out; 2095 goto out;
2068 } 2096 }
2069 2097
2070 ret = wl1271_ps_elp_wakeup(wl, false); 2098 ret = wl1271_ps_elp_wakeup(wl);
2071 if (ret < 0) 2099 if (ret < 0)
2072 goto out; 2100 goto out;
2073 2101
@@ -2546,7 +2574,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
2546 if (unlikely(wl->state == WL1271_STATE_OFF)) 2574 if (unlikely(wl->state == WL1271_STATE_OFF))
2547 goto out; 2575 goto out;
2548 2576
2549 ret = wl1271_ps_elp_wakeup(wl, false); 2577 ret = wl1271_ps_elp_wakeup(wl);
2550 if (ret < 0) 2578 if (ret < 0)
2551 goto out; 2579 goto out;
2552 2580
@@ -2601,7 +2629,7 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
2601 conf_tid->apsd_conf[0] = 0; 2629 conf_tid->apsd_conf[0] = 0;
2602 conf_tid->apsd_conf[1] = 0; 2630 conf_tid->apsd_conf[1] = 0;
2603 } else { 2631 } else {
2604 ret = wl1271_ps_elp_wakeup(wl, false); 2632 ret = wl1271_ps_elp_wakeup(wl);
2605 if (ret < 0) 2633 if (ret < 0)
2606 goto out; 2634 goto out;
2607 2635
@@ -2647,7 +2675,7 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw)
2647 if (unlikely(wl->state == WL1271_STATE_OFF)) 2675 if (unlikely(wl->state == WL1271_STATE_OFF))
2648 goto out; 2676 goto out;
2649 2677
2650 ret = wl1271_ps_elp_wakeup(wl, false); 2678 ret = wl1271_ps_elp_wakeup(wl);
2651 if (ret < 0) 2679 if (ret < 0)
2652 goto out; 2680 goto out;
2653 2681
@@ -2736,7 +2764,7 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
2736 if (ret < 0) 2764 if (ret < 0)
2737 goto out; 2765 goto out;
2738 2766
2739 ret = wl1271_ps_elp_wakeup(wl, false); 2767 ret = wl1271_ps_elp_wakeup(wl);
2740 if (ret < 0) 2768 if (ret < 0)
2741 goto out_free_sta; 2769 goto out_free_sta;
2742 2770
@@ -2779,7 +2807,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
2779 if (WARN_ON(!test_bit(id, wl->ap_hlid_map))) 2807 if (WARN_ON(!test_bit(id, wl->ap_hlid_map)))
2780 goto out; 2808 goto out;
2781 2809
2782 ret = wl1271_ps_elp_wakeup(wl, false); 2810 ret = wl1271_ps_elp_wakeup(wl);
2783 if (ret < 0) 2811 if (ret < 0)
2784 goto out; 2812 goto out;
2785 2813
@@ -2812,7 +2840,7 @@ int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2812 goto out; 2840 goto out;
2813 } 2841 }
2814 2842
2815 ret = wl1271_ps_elp_wakeup(wl, false); 2843 ret = wl1271_ps_elp_wakeup(wl);
2816 if (ret < 0) 2844 if (ret < 0)
2817 goto out; 2845 goto out;
2818 2846
@@ -3176,7 +3204,7 @@ static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev,
3176 if (wl->state == WL1271_STATE_OFF) 3204 if (wl->state == WL1271_STATE_OFF)
3177 goto out; 3205 goto out;
3178 3206
3179 ret = wl1271_ps_elp_wakeup(wl, false); 3207 ret = wl1271_ps_elp_wakeup(wl);
3180 if (ret < 0) 3208 if (ret < 0)
3181 goto out; 3209 goto out;
3182 3210
@@ -3376,9 +3404,12 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
3376 for (j = 0; j < AP_MAX_LINKS; j++) 3404 for (j = 0; j < AP_MAX_LINKS; j++)
3377 skb_queue_head_init(&wl->links[j].tx_queue[i]); 3405 skb_queue_head_init(&wl->links[j].tx_queue[i]);
3378 3406
3407 skb_queue_head_init(&wl->deferred_rx_queue);
3408 skb_queue_head_init(&wl->deferred_tx_queue);
3409
3379 INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); 3410 INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
3380 INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); 3411 INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work);
3381 INIT_WORK(&wl->irq_work, wl1271_irq_work); 3412 INIT_WORK(&wl->netstack_work, wl1271_netstack_work);
3382 INIT_WORK(&wl->tx_work, wl1271_tx_work); 3413 INIT_WORK(&wl->tx_work, wl1271_tx_work);
3383 INIT_WORK(&wl->recovery_work, wl1271_recovery_work); 3414 INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
3384 INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); 3415 INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index 5c347b1bd17f..971f13e792da 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -69,7 +69,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
69 } 69 }
70} 70}
71 71
72int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) 72int wl1271_ps_elp_wakeup(struct wl1271 *wl)
73{ 73{
74 DECLARE_COMPLETION_ONSTACK(compl); 74 DECLARE_COMPLETION_ONSTACK(compl);
75 unsigned long flags; 75 unsigned long flags;
@@ -87,7 +87,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
87 * the completion variable in one entity. 87 * the completion variable in one entity.
88 */ 88 */
89 spin_lock_irqsave(&wl->wl_lock, flags); 89 spin_lock_irqsave(&wl->wl_lock, flags);
90 if (work_pending(&wl->irq_work) || chip_awake) 90 if (test_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
91 pending = true; 91 pending = true;
92 else 92 else
93 wl->elp_compl = &compl; 93 wl->elp_compl = &compl;
@@ -149,7 +149,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
149 case STATION_ACTIVE_MODE: 149 case STATION_ACTIVE_MODE:
150 default: 150 default:
151 wl1271_debug(DEBUG_PSM, "leaving psm"); 151 wl1271_debug(DEBUG_PSM, "leaving psm");
152 ret = wl1271_ps_elp_wakeup(wl, false); 152 ret = wl1271_ps_elp_wakeup(wl);
153 if (ret < 0) 153 if (ret < 0)
154 return ret; 154 return ret;
155 155
diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/wl12xx/ps.h
index fc1f4c193593..c41bd0a711bc 100644
--- a/drivers/net/wireless/wl12xx/ps.h
+++ b/drivers/net/wireless/wl12xx/ps.h
@@ -30,7 +30,7 @@
30int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, 30int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
31 u32 rates, bool send); 31 u32 rates, bool send);
32void wl1271_ps_elp_sleep(struct wl1271 *wl); 32void wl1271_ps_elp_sleep(struct wl1271 *wl);
33int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); 33int wl1271_ps_elp_wakeup(struct wl1271 *wl);
34void wl1271_elp_work(struct work_struct *work); 34void wl1271_elp_work(struct work_struct *work);
35void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues); 35void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues);
36void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid); 36void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid);
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
index 4e7a3b311321..919b59f00301 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/rx.c
@@ -129,7 +129,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
129 129
130 skb_trim(skb, skb->len - desc->pad_len); 130 skb_trim(skb, skb->len - desc->pad_len);
131 131
132 ieee80211_rx_ni(wl->hw, skb); 132 skb_queue_tail(&wl->deferred_rx_queue, skb);
133 ieee80211_queue_work(wl->hw, &wl->netstack_work);
133 134
134 return 0; 135 return 0;
135} 136}
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index 61fdc9e981bd..b66abb5ebcf3 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -61,7 +61,7 @@ static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl)
61 return &(wl_to_func(wl)->dev); 61 return &(wl_to_func(wl)->dev);
62} 62}
63 63
64static irqreturn_t wl1271_irq(int irq, void *cookie) 64static irqreturn_t wl1271_hardirq(int irq, void *cookie)
65{ 65{
66 struct wl1271 *wl = cookie; 66 struct wl1271 *wl = cookie;
67 unsigned long flags; 67 unsigned long flags;
@@ -70,17 +70,14 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
70 70
71 /* complete the ELP completion */ 71 /* complete the ELP completion */
72 spin_lock_irqsave(&wl->wl_lock, flags); 72 spin_lock_irqsave(&wl->wl_lock, flags);
73 set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
73 if (wl->elp_compl) { 74 if (wl->elp_compl) {
74 complete(wl->elp_compl); 75 complete(wl->elp_compl);
75 wl->elp_compl = NULL; 76 wl->elp_compl = NULL;
76 } 77 }
77
78 if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
79 ieee80211_queue_work(wl->hw, &wl->irq_work);
80 set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags);
81 spin_unlock_irqrestore(&wl->wl_lock, flags); 78 spin_unlock_irqrestore(&wl->wl_lock, flags);
82 79
83 return IRQ_HANDLED; 80 return IRQ_WAKE_THREAD;
84} 81}
85 82
86static void wl1271_sdio_disable_interrupts(struct wl1271 *wl) 83static void wl1271_sdio_disable_interrupts(struct wl1271 *wl)
@@ -243,14 +240,14 @@ static int __devinit wl1271_probe(struct sdio_func *func,
243 wl->irq = wlan_data->irq; 240 wl->irq = wlan_data->irq;
244 wl->ref_clock = wlan_data->board_ref_clock; 241 wl->ref_clock = wlan_data->board_ref_clock;
245 242
246 ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); 243 ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
244 IRQF_TRIGGER_RISING,
245 DRIVER_NAME, wl);
247 if (ret < 0) { 246 if (ret < 0) {
248 wl1271_error("request_irq() failed: %d", ret); 247 wl1271_error("request_irq() failed: %d", ret);
249 goto out_free; 248 goto out_free;
250 } 249 }
251 250
252 set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
253
254 disable_irq(wl->irq); 251 disable_irq(wl->irq);
255 252
256 ret = wl1271_init_ieee80211(wl); 253 ret = wl1271_init_ieee80211(wl);
@@ -273,7 +270,6 @@ static int __devinit wl1271_probe(struct sdio_func *func,
273 out_irq: 270 out_irq:
274 free_irq(wl->irq, wl); 271 free_irq(wl->irq, wl);
275 272
276
277 out_free: 273 out_free:
278 wl1271_free_hw(wl); 274 wl1271_free_hw(wl);
279 275
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index 0132dad756c4..df5a00f103ea 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -320,28 +320,23 @@ static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
320 spi_sync(wl_to_spi(wl), &m); 320 spi_sync(wl_to_spi(wl), &m);
321} 321}
322 322
323static irqreturn_t wl1271_irq(int irq, void *cookie) 323static irqreturn_t wl1271_hardirq(int irq, void *cookie)
324{ 324{
325 struct wl1271 *wl; 325 struct wl1271 *wl = cookie;
326 unsigned long flags; 326 unsigned long flags;
327 327
328 wl1271_debug(DEBUG_IRQ, "IRQ"); 328 wl1271_debug(DEBUG_IRQ, "IRQ");
329 329
330 wl = cookie;
331
332 /* complete the ELP completion */ 330 /* complete the ELP completion */
333 spin_lock_irqsave(&wl->wl_lock, flags); 331 spin_lock_irqsave(&wl->wl_lock, flags);
332 set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
334 if (wl->elp_compl) { 333 if (wl->elp_compl) {
335 complete(wl->elp_compl); 334 complete(wl->elp_compl);
336 wl->elp_compl = NULL; 335 wl->elp_compl = NULL;
337 } 336 }
338
339 if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
340 ieee80211_queue_work(wl->hw, &wl->irq_work);
341 set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags);
342 spin_unlock_irqrestore(&wl->wl_lock, flags); 337 spin_unlock_irqrestore(&wl->wl_lock, flags);
343 338
344 return IRQ_HANDLED; 339 return IRQ_WAKE_THREAD;
345} 340}
346 341
347static int wl1271_spi_set_power(struct wl1271 *wl, bool enable) 342static int wl1271_spi_set_power(struct wl1271 *wl, bool enable)
@@ -413,14 +408,14 @@ static int __devinit wl1271_probe(struct spi_device *spi)
413 goto out_free; 408 goto out_free;
414 } 409 }
415 410
416 ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); 411 ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
412 IRQF_TRIGGER_RISING,
413 DRIVER_NAME, wl);
417 if (ret < 0) { 414 if (ret < 0) {
418 wl1271_error("request_irq() failed: %d", ret); 415 wl1271_error("request_irq() failed: %d", ret);
419 goto out_free; 416 goto out_free;
420 } 417 }
421 418
422 set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
423
424 disable_irq(wl->irq); 419 disable_irq(wl->irq);
425 420
426 ret = wl1271_init_ieee80211(wl); 421 ret = wl1271_init_ieee80211(wl);
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 455954edf83e..5e9ef7d53e7e 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -464,7 +464,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
464 464
465 while ((skb = wl1271_skb_dequeue(wl))) { 465 while ((skb = wl1271_skb_dequeue(wl))) {
466 if (!woken_up) { 466 if (!woken_up) {
467 ret = wl1271_ps_elp_wakeup(wl, false); 467 ret = wl1271_ps_elp_wakeup(wl);
468 if (ret < 0) 468 if (ret < 0)
469 goto out_ack; 469 goto out_ack;
470 woken_up = true; 470 woken_up = true;
@@ -589,7 +589,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
589 result->rate_class_index, result->status); 589 result->rate_class_index, result->status);
590 590
591 /* return the packet to the stack */ 591 /* return the packet to the stack */
592 ieee80211_tx_status(wl->hw, skb); 592 skb_queue_tail(&wl->deferred_tx_queue, skb);
593 ieee80211_queue_work(wl->hw, &wl->netstack_work);
593 wl1271_free_tx_id(wl, result->id); 594 wl1271_free_tx_id(wl, result->id);
594} 595}
595 596
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index ea1eee7895cf..e395c0c4ebbd 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -320,7 +320,6 @@ enum wl12xx_flags {
320 WL1271_FLAG_IN_ELP, 320 WL1271_FLAG_IN_ELP,
321 WL1271_FLAG_PSM, 321 WL1271_FLAG_PSM,
322 WL1271_FLAG_PSM_REQUESTED, 322 WL1271_FLAG_PSM_REQUESTED,
323 WL1271_FLAG_IRQ_PENDING,
324 WL1271_FLAG_IRQ_RUNNING, 323 WL1271_FLAG_IRQ_RUNNING,
325 WL1271_FLAG_IDLE, 324 WL1271_FLAG_IDLE,
326 WL1271_FLAG_IDLE_REQUESTED, 325 WL1271_FLAG_IDLE_REQUESTED,
@@ -404,6 +403,12 @@ struct wl1271 {
404 struct sk_buff_head tx_queue[NUM_TX_QUEUES]; 403 struct sk_buff_head tx_queue[NUM_TX_QUEUES];
405 int tx_queue_count; 404 int tx_queue_count;
406 405
406 /* Frames received, not handled yet by mac80211 */
407 struct sk_buff_head deferred_rx_queue;
408
409 /* Frames sent, not returned yet to mac80211 */
410 struct sk_buff_head deferred_tx_queue;
411
407 struct work_struct tx_work; 412 struct work_struct tx_work;
408 413
409 /* Pending TX frames */ 414 /* Pending TX frames */
@@ -424,8 +429,8 @@ struct wl1271 {
424 /* Intermediate buffer, used for packet aggregation */ 429 /* Intermediate buffer, used for packet aggregation */
425 u8 *aggr_buf; 430 u8 *aggr_buf;
426 431
427 /* The target interrupt mask */ 432 /* Network stack work */
428 struct work_struct irq_work; 433 struct work_struct netstack_work;
429 434
430 /* Hardware recovery work */ 435 /* Hardware recovery work */
431 struct work_struct recovery_work; 436 struct work_struct recovery_work;
@@ -556,6 +561,8 @@ int wl1271_plt_stop(struct wl1271 *wl);
556#define WL1271_TX_QUEUE_LOW_WATERMARK 10 561#define WL1271_TX_QUEUE_LOW_WATERMARK 10
557#define WL1271_TX_QUEUE_HIGH_WATERMARK 25 562#define WL1271_TX_QUEUE_HIGH_WATERMARK 25
558 563
564#define WL1271_DEFERRED_QUEUE_LIMIT 64
565
559/* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power 566/* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power
560 on in case is has been shut down shortly before */ 567 on in case is has been shut down shortly before */
561#define WL1271_PRE_POWER_ON_SLEEP 20 /* in milliseconds */ 568#define WL1271_PRE_POWER_ON_SLEEP 20 /* in milliseconds */