提交 446075d7 编写于 作者: M Marco Porsch 提交者: Johannes Berg

mac80211: fixes for mesh powersave logic

This patch fixes errors in the mesh powersave logic which
cause that remote peers do not get peer power mode change
notifications and mesh peer service periods (MPSPs) got
stuck.

When closing a peer link, set the (now invalid) peer-specific
power mode to 'unknown'.

Avoid overhead when local power mode is unchanged.

Reliably clear MPSP flags on peering status update.

Avoid MPSP flags getting stuck by not requesting a further
MPSP ownership if we already are an MPSP owner.
Signed-off-by: NMarco Porsch <marco@cozybit.com>
Signed-off-by: NJohannes Berg <johannes.berg@intel.com>
上级 17ac4959
...@@ -1343,8 +1343,8 @@ static int sta_apply_parameters(struct ieee80211_local *local, ...@@ -1343,8 +1343,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,
sta->plink_state = params->plink_state; sta->plink_state = params->plink_state;
ieee80211_mps_sta_status_update(sta); ieee80211_mps_sta_status_update(sta);
changed |= changed |= ieee80211_mps_set_sta_local_pm(sta,
ieee80211_mps_local_status_update(sdata); NL80211_MESH_POWER_UNKNOWN);
break; break;
default: default:
/* nothing */ /* nothing */
......
...@@ -222,7 +222,8 @@ static u32 __mesh_plink_deactivate(struct sta_info *sta) ...@@ -222,7 +222,8 @@ static u32 __mesh_plink_deactivate(struct sta_info *sta)
mesh_path_flush_by_nexthop(sta); mesh_path_flush_by_nexthop(sta);
ieee80211_mps_sta_status_update(sta); ieee80211_mps_sta_status_update(sta);
changed |= ieee80211_mps_local_status_update(sdata); changed |= ieee80211_mps_set_sta_local_pm(sta,
NL80211_MESH_POWER_UNKNOWN);
return changed; return changed;
} }
......
...@@ -152,6 +152,9 @@ u32 ieee80211_mps_set_sta_local_pm(struct sta_info *sta, ...@@ -152,6 +152,9 @@ u32 ieee80211_mps_set_sta_local_pm(struct sta_info *sta,
{ {
struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_sub_if_data *sdata = sta->sdata;
if (sta->local_pm == pm)
return 0;
mps_dbg(sdata, "local STA operates in mode %d with %pM\n", mps_dbg(sdata, "local STA operates in mode %d with %pM\n",
pm, sta->sta.addr); pm, sta->sta.addr);
...@@ -245,6 +248,14 @@ void ieee80211_mps_sta_status_update(struct sta_info *sta) ...@@ -245,6 +248,14 @@ void ieee80211_mps_sta_status_update(struct sta_info *sta)
do_buffer = (pm != NL80211_MESH_POWER_ACTIVE); do_buffer = (pm != NL80211_MESH_POWER_ACTIVE);
/* clear the MPSP flags for non-peers or active STA */
if (sta->plink_state != NL80211_PLINK_ESTAB) {
clear_sta_flag(sta, WLAN_STA_MPSP_OWNER);
clear_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT);
} else if (!do_buffer) {
clear_sta_flag(sta, WLAN_STA_MPSP_OWNER);
}
/* Don't let the same PS state be set twice */ /* Don't let the same PS state be set twice */
if (test_sta_flag(sta, WLAN_STA_PS_STA) == do_buffer) if (test_sta_flag(sta, WLAN_STA_PS_STA) == do_buffer)
return; return;
...@@ -257,14 +268,6 @@ void ieee80211_mps_sta_status_update(struct sta_info *sta) ...@@ -257,14 +268,6 @@ void ieee80211_mps_sta_status_update(struct sta_info *sta)
} else { } else {
ieee80211_sta_ps_deliver_wakeup(sta); ieee80211_sta_ps_deliver_wakeup(sta);
} }
/* clear the MPSP flags for non-peers or active STA */
if (sta->plink_state != NL80211_PLINK_ESTAB) {
clear_sta_flag(sta, WLAN_STA_MPSP_OWNER);
clear_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT);
} else if (!do_buffer) {
clear_sta_flag(sta, WLAN_STA_MPSP_OWNER);
}
} }
static void mps_set_sta_peer_pm(struct sta_info *sta, static void mps_set_sta_peer_pm(struct sta_info *sta,
...@@ -444,8 +447,7 @@ static void mpsp_qos_null_append(struct sta_info *sta, ...@@ -444,8 +447,7 @@ static void mpsp_qos_null_append(struct sta_info *sta,
*/ */
static void mps_frame_deliver(struct sta_info *sta, int n_frames) static void mps_frame_deliver(struct sta_info *sta, int n_frames)
{ {
struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_local *local = sta->sdata->local;
struct ieee80211_local *local = sdata->local;
int ac; int ac;
struct sk_buff_head frames; struct sk_buff_head frames;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -558,10 +560,10 @@ void ieee80211_mpsp_trigger_process(u8 *qc, struct sta_info *sta, ...@@ -558,10 +560,10 @@ void ieee80211_mpsp_trigger_process(u8 *qc, struct sta_info *sta,
} }
/** /**
* ieee80211_mps_frame_release - release buffered frames in response to beacon * ieee80211_mps_frame_release - release frames buffered due to mesh power save
* *
* @sta: mesh STA * @sta: mesh STA
* @elems: beacon IEs * @elems: IEs of beacon or probe response
* *
* For peers if we have individually-addressed frames buffered or the peer * For peers if we have individually-addressed frames buffered or the peer
* indicates buffered frames, send a corresponding MPSP trigger frame. Since * indicates buffered frames, send a corresponding MPSP trigger frame. Since
...@@ -588,9 +590,10 @@ void ieee80211_mps_frame_release(struct sta_info *sta, ...@@ -588,9 +590,10 @@ void ieee80211_mps_frame_release(struct sta_info *sta,
(!elems->awake_window || !le16_to_cpu(*elems->awake_window))) (!elems->awake_window || !le16_to_cpu(*elems->awake_window)))
return; return;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) if (!test_sta_flag(sta, WLAN_STA_MPSP_OWNER))
buffer_local += skb_queue_len(&sta->ps_tx_buf[ac]) + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
skb_queue_len(&sta->tx_filtered[ac]); buffer_local += skb_queue_len(&sta->ps_tx_buf[ac]) +
skb_queue_len(&sta->tx_filtered[ac]);
if (!has_buffered && !buffer_local) if (!has_buffered && !buffer_local)
return; return;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册