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.c49
1 files changed, 47 insertions, 2 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index dac8bd37dcf5..5ba721b6a399 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -745,8 +745,14 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
745 ieee80211_bss_info_change_notify(sdata, bss_info_changed); 745 ieee80211_bss_info_change_notify(sdata, bss_info_changed);
746 746
747 if (local->powersave) { 747 if (local->powersave) {
748 local->hw.conf.flags |= IEEE80211_CONF_PS; 748 if (local->dynamic_ps_timeout > 0)
749 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); 749 mod_timer(&local->dynamic_ps_timer, jiffies +
750 msecs_to_jiffies(local->dynamic_ps_timeout));
751 else {
752 conf->flags |= IEEE80211_CONF_PS;
753 ieee80211_hw_config(local,
754 IEEE80211_CONF_CHANGE_PS);
755 }
750 } 756 }
751 757
752 netif_tx_start_all_queues(sdata->dev); 758 netif_tx_start_all_queues(sdata->dev);
@@ -866,6 +872,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
866 local->oper_channel_type = NL80211_CHAN_NO_HT; 872 local->oper_channel_type = NL80211_CHAN_NO_HT;
867 config_changed |= IEEE80211_CONF_CHANGE_HT; 873 config_changed |= IEEE80211_CONF_CHANGE_HT;
868 874
875 del_timer_sync(&local->dynamic_ps_timer);
876 cancel_work_sync(&local->dynamic_ps_enable_work);
877
869 if (local->hw.conf.flags & IEEE80211_CONF_PS) { 878 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
870 local->hw.conf.flags &= ~IEEE80211_CONF_PS; 879 local->hw.conf.flags &= ~IEEE80211_CONF_PS;
871 config_changed |= IEEE80211_CONF_CHANGE_PS; 880 config_changed |= IEEE80211_CONF_CHANGE_PS;
@@ -2593,3 +2602,39 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
2593 ieee80211_restart_sta_timer(sdata); 2602 ieee80211_restart_sta_timer(sdata);
2594 rcu_read_unlock(); 2603 rcu_read_unlock();
2595} 2604}
2605
2606void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
2607{
2608 struct ieee80211_local *local =
2609 container_of(work, struct ieee80211_local,
2610 dynamic_ps_disable_work);
2611
2612 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
2613 local->hw.conf.flags &= ~IEEE80211_CONF_PS;
2614 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
2615 }
2616
2617 ieee80211_wake_queues_by_reason(&local->hw,
2618 IEEE80211_QUEUE_STOP_REASON_PS);
2619}
2620
2621void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
2622{
2623 struct ieee80211_local *local =
2624 container_of(work, struct ieee80211_local,
2625 dynamic_ps_enable_work);
2626
2627 if (local->hw.conf.flags & IEEE80211_CONF_PS)
2628 return;
2629
2630 local->hw.conf.flags |= IEEE80211_CONF_PS;
2631
2632 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
2633}
2634
2635void ieee80211_dynamic_ps_timer(unsigned long data)
2636{
2637 struct ieee80211_local *local = (void *) data;
2638
2639 queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work);
2640}