On Fri, Oct 19, 2012 at 6:00 PM, <[email protected]> wrote:
> From: Marco Porsch <[email protected]>
>
> In case of a neighbor changing its power mode or peering status,
> ieee80211_sta_ps_transition is called, which sets or clears the
> WLAN_STA_PS flag. This triggers the frame buffering routines for
> individually-addressed frames in the tx path used for client mode, which are
> re-used here.
> Also the num_sta_ps counter is updated, which will trigger the buffering
> and release of group-addressed frames after DTIM beacons.
>
> Signed-off-by: Marco Porsch <[email protected]>
> ---
> net/mac80211/mesh.h | 1 +
> net/mac80211/mesh_plink.c | 3 +++
> net/mac80211/mesh_ps.c | 36 ++++++++++++++++++++++++++++++++++++
> net/mac80211/rx.c | 3 ++-
> 4 files changed, 42 insertions(+), 1 deletion(-)
>
> diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
> index 23c2bf3..cb70522 100644
> --- a/net/mac80211/mesh.h
> +++ b/net/mac80211/mesh.h
> @@ -265,6 +265,7 @@ void ieee80211_set_local_ps_mode(struct sta_info *sta,
> void ieee80211_set_mesh_ps_flags(struct ieee80211_sub_if_data *sdata,
> struct sta_info *sta,
> struct ieee80211_hdr *hdr);
> +void ieee80211_sta_ps_update(struct sta_info *sta);
> void ieee80211_set_peer_ps_mode(struct sta_info *sta,
> struct ieee80211_hdr *hdr);
> void ieee80211_set_nonpeer_ps_mode(struct sta_info *sta,
> diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
> index 41b289d..70ae26f 100644
> --- a/net/mac80211/mesh_plink.c
> +++ b/net/mac80211/mesh_plink.c
> @@ -186,6 +186,7 @@ static u32 __mesh_plink_deactivate(struct sta_info *sta)
> sta->plink_state = NL80211_PLINK_BLOCKED;
> mesh_path_flush_by_nexthop(sta);
>
> + ieee80211_sta_ps_update(sta);
> ieee80211_local_ps_update(sdata);
>
> return changed;
> @@ -881,6 +882,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data
> *sdata, struct ieee80211_m
> mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
> sta->sta.addr);
>
> + ieee80211_sta_ps_update(sta);
> ieee80211_set_local_ps_mode(sta,
> default_ps_mode(sdata),
> 100);
> @@ -922,6 +924,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data
> *sdata, struct ieee80211_m
> mesh_plink_frame_tx(sdata,
> WLAN_SP_MESH_PEERING_CONFIRM,
> sta->sta.addr, llid, plid, 0);
> + ieee80211_sta_ps_update(sta);
> /*
> * we need some delay here, otherwise
> * the announcement Null would arrive before the
> CONFIRM
> diff --git a/net/mac80211/mesh_ps.c b/net/mac80211/mesh_ps.c
> index 6569ca7..a3914e1 100644
> --- a/net/mac80211/mesh_ps.c
> +++ b/net/mac80211/mesh_ps.c
> @@ -251,6 +251,42 @@ void ieee80211_set_mesh_ps_flags(struct
> ieee80211_sub_if_data *sdata,
> }
>
> /**
> + * ieee80211_sta_ps_update - update the buffering status for a neighbor STA
> + * after peering change or non-peer/peer-specific power mode change
> + *
> + * @sta: mesh STA
> + */
> +void ieee80211_sta_ps_update(struct sta_info *sta)
> +{
> + enum nl80211_mesh_power_mode pm;
> + bool do_buffer;
> +
> + /*
> + * use peer-specific power mode if peering is established and
> + * the peer's power mode is known
> + */
> + if (sta->plink_state == NL80211_PLINK_ESTAB &&
> + (sta->peer_ps_mode == NL80211_MESH_POWER_ACTIVE ||
> + sta->peer_ps_mode == NL80211_MESH_POWER_LIGHT_SLEEP ||
> + sta->peer_ps_mode == NL80211_MESH_POWER_DEEP_SLEEP))
> + pm = sta->peer_ps_mode;
> + else
> + pm = sta->nonpeer_ps_mode;
Sorry for missing something you must have introduced earlier, but why
do we have a per-STA nonpeer PS mode? Wouldn't the local nonpeer PS
mode be applicable here?
> + do_buffer = (pm == NL80211_MESH_POWER_LIGHT_SLEEP ||
> + pm == NL80211_MESH_POWER_DEEP_SLEEP);
> +
> + /* enable frame buffering for powersave STA */
> + ieee80211_sta_ps_transition_ni(&sta->sta, do_buffer);
> +
> + /* clear the PSP flags for non-peers */
> + if (sta->plink_state != NL80211_PLINK_ESTAB) {
> + clear_sta_flag(sta, WLAN_STA_PSP_PEER);
> + clear_sta_flag(sta, WLAN_STA_SP);
> + }
> +}
> +
> +/**
> * ieee80211_set_peer_ps_mode - track the neighbor mesh STA's peer-specific
> * power mode towards the local STA
> *
> diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
> index 1db753b..86ad476 100644
> --- a/net/mac80211/rx.c
> +++ b/net/mac80211/rx.c
> @@ -1182,7 +1182,8 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta
> *sta, bool start)
> struct sta_info *sta_inf = container_of(sta, struct sta_info, sta);
> bool in_ps;
>
> - WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS));
> + WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS) &&
> + !ieee80211_vif_is_mesh(&sta_inf->sdata->vif));
>
> /* Don't let the same PS state be set twice */
> in_ps = test_sta_flag(sta_inf, WLAN_STA_PS_STA);
> --
> 1.7.9.5
>
_______________________________________________
Devel mailing list
[email protected]
http://lists.open80211s.org/cgi-bin/mailman/listinfo/devel