aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorMarco Porsch <marco@cozybit.com>2013-10-15 06:29:24 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-10-28 10:05:26 -0400
commit446075d76b6cc48ed15c515e836dd1a1f25f4c3d (patch)
tree8e0029fb0d6bddf726c17fe141cc64072f3c4722 /net/mac80211
parent17ac49594fc574665e937f5804134087c0f37115 (diff)
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: Marco Porsch <marco@cozybit.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c4
-rw-r--r--net/mac80211/mesh_plink.c3
-rw-r--r--net/mac80211/mesh_ps.c33
3 files changed, 22 insertions, 18 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 4a3d5a414a25..67f62dac54f5 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1343,8 +1343,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,
1343 sta->plink_state = params->plink_state; 1343 sta->plink_state = params->plink_state;
1344 1344
1345 ieee80211_mps_sta_status_update(sta); 1345 ieee80211_mps_sta_status_update(sta);
1346 changed |= 1346 changed |= ieee80211_mps_set_sta_local_pm(sta,
1347 ieee80211_mps_local_status_update(sdata); 1347 NL80211_MESH_POWER_UNKNOWN);
1348 break; 1348 break;
1349 default: 1349 default:
1350 /* nothing */ 1350 /* nothing */
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 6b65d5055f5b..4301aa5aa227 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -222,7 +222,8 @@ static u32 __mesh_plink_deactivate(struct sta_info *sta)
222 mesh_path_flush_by_nexthop(sta); 222 mesh_path_flush_by_nexthop(sta);
223 223
224 ieee80211_mps_sta_status_update(sta); 224 ieee80211_mps_sta_status_update(sta);
225 changed |= ieee80211_mps_local_status_update(sdata); 225 changed |= ieee80211_mps_set_sta_local_pm(sta,
226 NL80211_MESH_POWER_UNKNOWN);
226 227
227 return changed; 228 return changed;
228} 229}
diff --git a/net/mac80211/mesh_ps.c b/net/mac80211/mesh_ps.c
index 22290a929b94..0f79b78b5e86 100644
--- a/net/mac80211/mesh_ps.c
+++ b/net/mac80211/mesh_ps.c
@@ -152,6 +152,9 @@ u32 ieee80211_mps_set_sta_local_pm(struct sta_info *sta,
152{ 152{
153 struct ieee80211_sub_if_data *sdata = sta->sdata; 153 struct ieee80211_sub_if_data *sdata = sta->sdata;
154 154
155 if (sta->local_pm == pm)
156 return 0;
157
155 mps_dbg(sdata, "local STA operates in mode %d with %pM\n", 158 mps_dbg(sdata, "local STA operates in mode %d with %pM\n",
156 pm, sta->sta.addr); 159 pm, sta->sta.addr);
157 160
@@ -245,6 +248,14 @@ void ieee80211_mps_sta_status_update(struct sta_info *sta)
245 248
246 do_buffer = (pm != NL80211_MESH_POWER_ACTIVE); 249 do_buffer = (pm != NL80211_MESH_POWER_ACTIVE);
247 250
251 /* clear the MPSP flags for non-peers or active STA */
252 if (sta->plink_state != NL80211_PLINK_ESTAB) {
253 clear_sta_flag(sta, WLAN_STA_MPSP_OWNER);
254 clear_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT);
255 } else if (!do_buffer) {
256 clear_sta_flag(sta, WLAN_STA_MPSP_OWNER);
257 }
258
248 /* Don't let the same PS state be set twice */ 259 /* Don't let the same PS state be set twice */
249 if (test_sta_flag(sta, WLAN_STA_PS_STA) == do_buffer) 260 if (test_sta_flag(sta, WLAN_STA_PS_STA) == do_buffer)
250 return; 261 return;
@@ -257,14 +268,6 @@ void ieee80211_mps_sta_status_update(struct sta_info *sta)
257 } else { 268 } else {
258 ieee80211_sta_ps_deliver_wakeup(sta); 269 ieee80211_sta_ps_deliver_wakeup(sta);
259 } 270 }
260
261 /* clear the MPSP flags for non-peers or active STA */
262 if (sta->plink_state != NL80211_PLINK_ESTAB) {
263 clear_sta_flag(sta, WLAN_STA_MPSP_OWNER);
264 clear_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT);
265 } else if (!do_buffer) {
266 clear_sta_flag(sta, WLAN_STA_MPSP_OWNER);
267 }
268} 271}
269 272
270static void mps_set_sta_peer_pm(struct sta_info *sta, 273static 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 */ 447 */
445static void mps_frame_deliver(struct sta_info *sta, int n_frames) 448static void mps_frame_deliver(struct sta_info *sta, int n_frames)
446{ 449{
447 struct ieee80211_sub_if_data *sdata = sta->sdata; 450 struct ieee80211_local *local = sta->sdata->local;
448 struct ieee80211_local *local = sdata->local;
449 int ac; 451 int ac;
450 struct sk_buff_head frames; 452 struct sk_buff_head frames;
451 struct sk_buff *skb; 453 struct sk_buff *skb;
@@ -558,10 +560,10 @@ void ieee80211_mpsp_trigger_process(u8 *qc, struct sta_info *sta,
558} 560}
559 561
560/** 562/**
561 * ieee80211_mps_frame_release - release buffered frames in response to beacon 563 * ieee80211_mps_frame_release - release frames buffered due to mesh power save
562 * 564 *
563 * @sta: mesh STA 565 * @sta: mesh STA
564 * @elems: beacon IEs 566 * @elems: IEs of beacon or probe response
565 * 567 *
566 * For peers if we have individually-addressed frames buffered or the peer 568 * For peers if we have individually-addressed frames buffered or the peer
567 * indicates buffered frames, send a corresponding MPSP trigger frame. Since 569 * indicates buffered frames, send a corresponding MPSP trigger frame. Since
@@ -588,9 +590,10 @@ void ieee80211_mps_frame_release(struct sta_info *sta,
588 (!elems->awake_window || !le16_to_cpu(*elems->awake_window))) 590 (!elems->awake_window || !le16_to_cpu(*elems->awake_window)))
589 return; 591 return;
590 592
591 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) 593 if (!test_sta_flag(sta, WLAN_STA_MPSP_OWNER))
592 buffer_local += skb_queue_len(&sta->ps_tx_buf[ac]) + 594 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
593 skb_queue_len(&sta->tx_filtered[ac]); 595 buffer_local += skb_queue_len(&sta->ps_tx_buf[ac]) +
596 skb_queue_len(&sta->tx_filtered[ac]);
594 597
595 if (!has_buffered && !buffer_local) 598 if (!has_buffered && !buffer_local)
596 return; 599 return;