diff options
-rw-r--r-- | drivers/net/wireless/wl12xx/debugfs.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/io.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 127 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/ps.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/ps.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/rx.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/sdio.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/spi.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 13 |
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); | |||
168 | int wl1271_init_ieee80211(struct wl1271 *wl); | 168 | int wl1271_init_ieee80211(struct wl1271 *wl); |
169 | struct ieee80211_hw *wl1271_alloc_hw(void); | 169 | struct ieee80211_hw *wl1271_alloc_hw(void); |
170 | int wl1271_free_hw(struct wl1271 *wl); | 170 | int wl1271_free_hw(struct wl1271 *wl); |
171 | irqreturn_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 | 638 | static 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 | |||
651 | static 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 | ||
640 | static void wl1271_irq_work(struct work_struct *work) | 661 | #define WL1271_IRQ_MAX_LOOPS 256 |
662 | |||
663 | irqreturn_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 | ||
734 | out: | 756 | out: |
735 | mutex_unlock(&wl->mutex); | 757 | mutex_unlock(&wl->mutex); |
758 | |||
759 | return IRQ_HANDLED; | ||
736 | } | 760 | } |
761 | EXPORT_SYMBOL_GPL(wl1271_irq); | ||
737 | 762 | ||
738 | static int wl1271_fetch_firmware(struct wl1271 *wl) | 763 | static 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 | ||
976 | irq_disable: | 1001 | irq_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); |
988 | power_off: | 1014 | power_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); |
1023 | out: | 1050 | out: |
@@ -1169,7 +1196,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
1169 | break; | 1196 | break; |
1170 | 1197 | ||
1171 | irq_disable: | 1198 | irq_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); |
1183 | power_off: | 1211 | power_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 | ||
72 | int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) | 72 | int 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 @@ | |||
30 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, | 30 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, |
31 | u32 rates, bool send); | 31 | u32 rates, bool send); |
32 | void wl1271_ps_elp_sleep(struct wl1271 *wl); | 32 | void wl1271_ps_elp_sleep(struct wl1271 *wl); |
33 | int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); | 33 | int wl1271_ps_elp_wakeup(struct wl1271 *wl); |
34 | void wl1271_elp_work(struct work_struct *work); | 34 | void wl1271_elp_work(struct work_struct *work); |
35 | void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues); | 35 | void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues); |
36 | void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid); | 36 | void 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 | ||
64 | static irqreturn_t wl1271_irq(int irq, void *cookie) | 64 | static 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 | ||
86 | static void wl1271_sdio_disable_interrupts(struct wl1271 *wl) | 83 | static 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 | ||
323 | static irqreturn_t wl1271_irq(int irq, void *cookie) | 323 | static 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 | ||
347 | static int wl1271_spi_set_power(struct wl1271 *wl, bool enable) | 342 | static 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 */ |