diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/tx.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.c | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 8c35d37ba600..a06aa4e8df7b 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -643,21 +643,58 @@ static bool wl1271_tx_is_data_present(struct sk_buff *skb) | |||
643 | return ieee80211_is_data_present(hdr->frame_control); | 643 | return ieee80211_is_data_present(hdr->frame_control); |
644 | } | 644 | } |
645 | 645 | ||
646 | void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids) | ||
647 | { | ||
648 | struct wl12xx_vif *wlvif; | ||
649 | u32 timeout; | ||
650 | u8 hlid; | ||
651 | |||
652 | if (!wl->conf.rx_streaming.interval) | ||
653 | return; | ||
654 | |||
655 | if (!wl->conf.rx_streaming.always && | ||
656 | !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)) | ||
657 | return; | ||
658 | |||
659 | timeout = wl->conf.rx_streaming.duration; | ||
660 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
661 | bool found = false; | ||
662 | for_each_set_bit(hlid, active_hlids, WL12XX_MAX_LINKS) { | ||
663 | if (test_bit(hlid, wlvif->links_map)) { | ||
664 | found = true; | ||
665 | break; | ||
666 | } | ||
667 | } | ||
668 | |||
669 | if (!found) | ||
670 | continue; | ||
671 | |||
672 | /* enable rx streaming */ | ||
673 | if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) | ||
674 | ieee80211_queue_work(wl->hw, | ||
675 | &wlvif->rx_streaming_enable_work); | ||
676 | |||
677 | mod_timer(&wlvif->rx_streaming_timer, | ||
678 | jiffies + msecs_to_jiffies(timeout)); | ||
679 | } | ||
680 | } | ||
681 | |||
646 | void wl1271_tx_work_locked(struct wl1271 *wl) | 682 | void wl1271_tx_work_locked(struct wl1271 *wl) |
647 | { | 683 | { |
648 | struct wl12xx_vif *wlvif; | 684 | struct wl12xx_vif *wlvif; |
649 | struct sk_buff *skb; | 685 | struct sk_buff *skb; |
686 | struct wl1271_tx_hw_descr *desc; | ||
650 | u32 buf_offset = 0; | 687 | u32 buf_offset = 0; |
651 | bool sent_packets = false; | 688 | bool sent_packets = false; |
652 | bool had_data = false; | 689 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; |
653 | /* TODO: save bitmap of relevant stations */ | ||
654 | bool is_sta = false; | ||
655 | int ret; | 690 | int ret; |
656 | 691 | ||
657 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 692 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
658 | return; | 693 | return; |
659 | 694 | ||
660 | while ((skb = wl1271_skb_dequeue(wl))) { | 695 | while ((skb = wl1271_skb_dequeue(wl))) { |
696 | bool has_data = false; | ||
697 | |||
661 | wlvif = NULL; | 698 | wlvif = NULL; |
662 | if (!wl12xx_is_dummy_packet(wl, skb)) { | 699 | if (!wl12xx_is_dummy_packet(wl, skb)) { |
663 | struct ieee80211_tx_info *info; | 700 | struct ieee80211_tx_info *info; |
@@ -667,9 +704,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
667 | vif = info->control.vif; | 704 | vif = info->control.vif; |
668 | wlvif = wl12xx_vif_to_data(vif); | 705 | wlvif = wl12xx_vif_to_data(vif); |
669 | } | 706 | } |
670 | 707 | has_data = wlvif && wl1271_tx_is_data_present(skb); | |
671 | if (wl1271_tx_is_data_present(skb)) | ||
672 | had_data = true; | ||
673 | 708 | ||
674 | ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset); | 709 | ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset); |
675 | if (ret == -EAGAIN) { | 710 | if (ret == -EAGAIN) { |
@@ -698,8 +733,10 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
698 | } | 733 | } |
699 | buf_offset += ret; | 734 | buf_offset += ret; |
700 | wl->tx_packets_count++; | 735 | wl->tx_packets_count++; |
701 | if (wlvif && wlvif->bss_type == BSS_TYPE_STA_BSS) | 736 | if (has_data) { |
702 | is_sta = true; | 737 | desc = (struct wl1271_tx_hw_descr *) skb->data; |
738 | __set_bit(desc->hlid, active_hlids); | ||
739 | } | ||
703 | } | 740 | } |
704 | 741 | ||
705 | out_ack: | 742 | out_ack: |
@@ -719,19 +756,7 @@ out_ack: | |||
719 | 756 | ||
720 | wl1271_handle_tx_low_watermark(wl); | 757 | wl1271_handle_tx_low_watermark(wl); |
721 | } | 758 | } |
722 | if (is_sta && wl->conf.rx_streaming.interval && had_data && | 759 | wl12xx_rearm_rx_streaming(wl, active_hlids); |
723 | (wl->conf.rx_streaming.always || | ||
724 | test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) { | ||
725 | u32 timeout = wl->conf.rx_streaming.duration; | ||
726 | |||
727 | /* enable rx streaming */ | ||
728 | if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) | ||
729 | ieee80211_queue_work(wl->hw, | ||
730 | &wl->rx_streaming_enable_work); | ||
731 | |||
732 | mod_timer(&wl->rx_streaming_timer, | ||
733 | jiffies + msecs_to_jiffies(timeout)); | ||
734 | } | ||
735 | } | 760 | } |
736 | 761 | ||
737 | void wl1271_tx_work(struct work_struct *work) | 762 | void wl1271_tx_work(struct work_struct *work) |