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

Reply via email to