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 64d92d5a7f4..4f6b2675e41 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)  |