aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c48
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
795void ieee80211_dynamic_ps_timer(unsigned long data) 807void ieee80211_dynamic_ps_timer(unsigned long data)