diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-07-27 00:54:47 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-07-27 00:54:47 -0700 |
commit | aa7eb8e78d8ecd6cd0475d86ea8385ff9cb47ece (patch) | |
tree | 3f9e98fadd5124fb05e8f6f9b06aa23698d4f215 /net/mac80211/mlme.c | |
parent | cca8edfd2ec2a34d9f50f593bc753bb11e1bc1f5 (diff) | |
parent | 3c6b50141ef9f0a8844bf1357b80c0cdf518bf05 (diff) |
Merge branch 'next' into for-linus
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 64d92d5a7f4..d595265d6c2 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -90,20 +90,11 @@ enum rx_mgmt_action { /* no action required */ RX_MGMT_NONE, - /* caller must call cfg80211_send_rx_auth() */ - RX_MGMT_CFG80211_AUTH, - - /* caller must call cfg80211_send_rx_assoc() */ - RX_MGMT_CFG80211_ASSOC, - /* caller must call cfg80211_send_deauth() */ RX_MGMT_CFG80211_DEAUTH, /* caller must call cfg80211_send_disassoc() */ RX_MGMT_CFG80211_DISASSOC, - - /* caller must tell cfg80211 about internal error */ - RX_MGMT_CFG80211_ASSOC_ERROR, }; /* utils */ @@ -759,6 +750,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) dynamic_ps_enable_work); struct ieee80211_sub_if_data *sdata = local->ps_sdata; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + unsigned long flags; + int q; /* can only happen when PS was just disabled anyway */ if (!sdata) @@ -767,18 +760,37 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) if (local->hw.conf.flags & IEEE80211_CONF_PS) return; + /* + * transmission can be stopped by others which leads to + * dynamic_ps_timer expiry. Postpond the ps timer if it + * is not the actual idle state. + */ + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + for (q = 0; q < local->hw.queues; q++) { + if (local->queue_stop_reasons[q]) { + spin_unlock_irqrestore(&local->queue_stop_reason_lock, + flags); + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies( + local->hw.conf.dynamic_ps_timeout)); + return; + } + } + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { netif_tx_stop_all_queues(sdata->dev); - /* - * Flush all the frames queued in the driver before - * going to power save - */ - drv_flush(local, false); - ieee80211_send_nullfunc(local, sdata, 1); - /* Flush once again to get the tx status of nullfunc frame */ - drv_flush(local, false); + if (drv_tx_frames_pending(local)) + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies( + local->hw.conf.dynamic_ps_timeout)); + else { + ieee80211_send_nullfunc(local, sdata, 1); + /* Flush to get the tx status of nullfunc frame */ + drv_flush(local, false); + } } if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) && @@ -789,7 +801,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); } - netif_tx_start_all_queues(sdata->dev); + netif_tx_wake_all_queues(sdata->dev); } void ieee80211_dynamic_ps_timer(unsigned long data) @@ -1077,6 +1089,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, local->hw.conf.flags &= ~IEEE80211_CONF_PS; config_changed |= IEEE80211_CONF_CHANGE_PS; } + local->ps_sdata = NULL; ieee80211_hw_config(local, config_changed); |