All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

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

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
......@@ -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);
......
......@@ -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);
......
......@@ -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)
{
......
......@@ -871,12 +871,17 @@ set:
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);
ret = ieee80211_hw_config(local,
IEEE80211_CONF_CHANGE_PS);
ieee80211_send_nullfunc(local, sdata, 0);
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment