Commit a97b77b9 authored by Vivek Natarajan's avatar Vivek Natarajan Committed by John W. Linville
Browse files

mac80211: Enhancements to dynamic power save.



This patch enables mac80211 to send a null frame and also to
check for tim in the beacon if dynamic power save is enabled.

Signed-off-by: default avatarVivek Natarajan <vnatarajan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 869717fb
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -987,6 +987,9 @@ u64 ieee80211_mandatory_rates(struct ieee80211_local *local,
void ieee80211_dynamic_ps_enable_work(struct work_struct *work);
void ieee80211_dynamic_ps_disable_work(struct work_struct *work);
void ieee80211_dynamic_ps_timer(unsigned long data);
void ieee80211_send_nullfunc(struct ieee80211_local *local,
			     struct ieee80211_sub_if_data *sdata,
			     int powersave);

void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
				     enum queue_stop_reason reason);
+40 −1
Original line number Diff line number Diff line
@@ -575,6 +575,30 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
	}
}

static bool check_tim(struct ieee802_11_elems *elems, u16 aid, bool *is_mc)
{
	u8 mask;
	u8 index, indexn1, indexn2;
	struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *) elems->tim;

	aid &= 0x3fff;
	index = aid / 8;
	mask  = 1 << (aid & 7);

	if (tim->bitmap_ctrl & 0x01)
		*is_mc = true;

	indexn1 = tim->bitmap_ctrl & 0xfe;
	indexn2 = elems->tim_len + indexn1 - 4;

	if (index < indexn1 || index > indexn2)
		return false;

	index -= indexn1;

	return !!(tim->virtual_map[index] & mask);
}

static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
					   u16 capab, bool erp_valid, u8 erp)
{
@@ -757,6 +781,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
			mod_timer(&local->dynamic_ps_timer, jiffies +
				  msecs_to_jiffies(local->dynamic_ps_timeout));
		else {
			ieee80211_send_nullfunc(local, sdata, 1);
			conf->flags |= IEEE80211_CONF_PS;
			ieee80211_hw_config(local,
					    IEEE80211_CONF_CHANGE_PS);
@@ -1720,7 +1745,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
	struct ieee802_11_elems elems;
	struct ieee80211_local *local = sdata->local;
	u32 changed = 0;
	bool erp_valid;
	bool erp_valid, directed_tim, is_mc = false;
	u8 erp_value = 0;

	/* Process beacon from the current BSS */
@@ -1743,6 +1768,18 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
	ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param,
				 elems.wmm_param_len);

	if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS)) {
		directed_tim = check_tim(&elems, ifsta->aid, &is_mc);

		if (directed_tim || is_mc) {
			if (local->hw.conf.flags && IEEE80211_CONF_PS) {
				local->hw.conf.flags &= ~IEEE80211_CONF_PS;
				ieee80211_hw_config(local,
						IEEE80211_CONF_CHANGE_PS);
				ieee80211_send_nullfunc(local, sdata, 0);
			}
		}
	}

	if (elems.erp_info && elems.erp_info_len >= 1) {
		erp_valid = true;
@@ -2631,10 +2668,12 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
	struct ieee80211_local *local =
		container_of(work, struct ieee80211_local,
			     dynamic_ps_enable_work);
	struct ieee80211_sub_if_data *sdata = local->scan_sdata;

	if (local->hw.conf.flags & IEEE80211_CONF_PS)
		return;

	ieee80211_send_nullfunc(local, sdata, 1);
	local->hw.conf.flags |= IEEE80211_CONF_PS;

	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+1 −1
Original line number Diff line number Diff line
@@ -395,7 +395,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
	return RX_QUEUED;
}

static void ieee80211_send_nullfunc(struct ieee80211_local *local,
void ieee80211_send_nullfunc(struct ieee80211_local *local,
				    struct ieee80211_sub_if_data *sdata,
				    int powersave)
{
+9 −4
Original line number Diff line number Diff line
@@ -871,12 +871,17 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
			mod_timer(&local->dynamic_ps_timer, jiffies +
				  msecs_to_jiffies(local->dynamic_ps_timeout));
		else {
			if (local->powersave)
			if (local->powersave) {
				ieee80211_send_nullfunc(local, sdata, 1);
				conf->flags |= IEEE80211_CONF_PS;
			else
				ret = ieee80211_hw_config(local,
						IEEE80211_CONF_CHANGE_PS);
			} else {
				conf->flags &= ~IEEE80211_CONF_PS;
				ret = ieee80211_hw_config(local,
						IEEE80211_CONF_CHANGE_PS);
				ieee80211_send_nullfunc(local, sdata, 0);
			}
		}
	}