diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 49 |
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 | |||
2606 | void 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 | |||
2621 | void 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 | |||
2635 | void 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 | } | ||