diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 48 |
1 files changed, 30 insertions, 18 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 64d92d5a7f40..4f6b2675e41d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -90,20 +90,11 @@ enum rx_mgmt_action { | |||
90 | /* no action required */ | 90 | /* no action required */ |
91 | RX_MGMT_NONE, | 91 | RX_MGMT_NONE, |
92 | 92 | ||
93 | /* caller must call cfg80211_send_rx_auth() */ | ||
94 | RX_MGMT_CFG80211_AUTH, | ||
95 | |||
96 | /* caller must call cfg80211_send_rx_assoc() */ | ||
97 | RX_MGMT_CFG80211_ASSOC, | ||
98 | |||
99 | /* caller must call cfg80211_send_deauth() */ | 93 | /* caller must call cfg80211_send_deauth() */ |
100 | RX_MGMT_CFG80211_DEAUTH, | 94 | RX_MGMT_CFG80211_DEAUTH, |
101 | 95 | ||
102 | /* caller must call cfg80211_send_disassoc() */ | 96 | /* caller must call cfg80211_send_disassoc() */ |
103 | RX_MGMT_CFG80211_DISASSOC, | 97 | RX_MGMT_CFG80211_DISASSOC, |
104 | |||
105 | /* caller must tell cfg80211 about internal error */ | ||
106 | RX_MGMT_CFG80211_ASSOC_ERROR, | ||
107 | }; | 98 | }; |
108 | 99 | ||
109 | /* utils */ | 100 | /* utils */ |
@@ -759,6 +750,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
759 | dynamic_ps_enable_work); | 750 | dynamic_ps_enable_work); |
760 | struct ieee80211_sub_if_data *sdata = local->ps_sdata; | 751 | struct ieee80211_sub_if_data *sdata = local->ps_sdata; |
761 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 752 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
753 | unsigned long flags; | ||
754 | int q; | ||
762 | 755 | ||
763 | /* can only happen when PS was just disabled anyway */ | 756 | /* can only happen when PS was just disabled anyway */ |
764 | if (!sdata) | 757 | if (!sdata) |
@@ -767,18 +760,37 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
767 | if (local->hw.conf.flags & IEEE80211_CONF_PS) | 760 | if (local->hw.conf.flags & IEEE80211_CONF_PS) |
768 | return; | 761 | return; |
769 | 762 | ||
763 | /* | ||
764 | * transmission can be stopped by others which leads to | ||
765 | * dynamic_ps_timer expiry. Postpond the ps timer if it | ||
766 | * is not the actual idle state. | ||
767 | */ | ||
768 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
769 | for (q = 0; q < local->hw.queues; q++) { | ||
770 | if (local->queue_stop_reasons[q]) { | ||
771 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | ||
772 | flags); | ||
773 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
774 | msecs_to_jiffies( | ||
775 | local->hw.conf.dynamic_ps_timeout)); | ||
776 | return; | ||
777 | } | ||
778 | } | ||
779 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
780 | |||
770 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && | 781 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && |
771 | (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { | 782 | (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { |
772 | netif_tx_stop_all_queues(sdata->dev); | 783 | netif_tx_stop_all_queues(sdata->dev); |
773 | /* | ||
774 | * Flush all the frames queued in the driver before | ||
775 | * going to power save | ||
776 | */ | ||
777 | drv_flush(local, false); | ||
778 | ieee80211_send_nullfunc(local, sdata, 1); | ||
779 | 784 | ||
780 | /* Flush once again to get the tx status of nullfunc frame */ | 785 | if (drv_tx_frames_pending(local)) |
781 | drv_flush(local, false); | 786 | mod_timer(&local->dynamic_ps_timer, jiffies + |
787 | msecs_to_jiffies( | ||
788 | local->hw.conf.dynamic_ps_timeout)); | ||
789 | else { | ||
790 | ieee80211_send_nullfunc(local, sdata, 1); | ||
791 | /* Flush to get the tx status of nullfunc frame */ | ||
792 | drv_flush(local, false); | ||
793 | } | ||
782 | } | 794 | } |
783 | 795 | ||
784 | if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) && | 796 | if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) && |
@@ -789,7 +801,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
789 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 801 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
790 | } | 802 | } |
791 | 803 | ||
792 | netif_tx_start_all_queues(sdata->dev); | 804 | netif_tx_wake_all_queues(sdata->dev); |
793 | } | 805 | } |
794 | 806 | ||
795 | void ieee80211_dynamic_ps_timer(unsigned long data) | 807 | void ieee80211_dynamic_ps_timer(unsigned long data) |