diff options
-rw-r--r-- | net/mac80211/mesh_plink.c | 30 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 2 |
2 files changed, 23 insertions, 9 deletions
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index e8f60aa2e848..63b874101b27 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -551,11 +551,30 @@ static void mesh_plink_timer(unsigned long data) | |||
551 | return; | 551 | return; |
552 | 552 | ||
553 | spin_lock_bh(&sta->lock); | 553 | spin_lock_bh(&sta->lock); |
554 | if (sta->ignore_plink_timer) { | 554 | |
555 | sta->ignore_plink_timer = false; | 555 | /* If a timer fires just before a state transition on another CPU, |
556 | * we may have already extended the timeout and changed state by the | ||
557 | * time we've acquired the lock and arrived here. In that case, | ||
558 | * skip this timer and wait for the new one. | ||
559 | */ | ||
560 | if (time_before(jiffies, sta->plink_timer.expires)) { | ||
561 | mpl_dbg(sta->sdata, | ||
562 | "Ignoring timer for %pM in state %s (timer adjusted)", | ||
563 | sta->sta.addr, mplstates[sta->plink_state]); | ||
556 | spin_unlock_bh(&sta->lock); | 564 | spin_unlock_bh(&sta->lock); |
557 | return; | 565 | return; |
558 | } | 566 | } |
567 | |||
568 | /* del_timer() and handler may race when entering these states */ | ||
569 | if (sta->plink_state == NL80211_PLINK_LISTEN || | ||
570 | sta->plink_state == NL80211_PLINK_ESTAB) { | ||
571 | mpl_dbg(sta->sdata, | ||
572 | "Ignoring timer for %pM in state %s (timer deleted)", | ||
573 | sta->sta.addr, mplstates[sta->plink_state]); | ||
574 | spin_unlock_bh(&sta->lock); | ||
575 | return; | ||
576 | } | ||
577 | |||
559 | mpl_dbg(sta->sdata, | 578 | mpl_dbg(sta->sdata, |
560 | "Mesh plink timer for %pM fired on state %s\n", | 579 | "Mesh plink timer for %pM fired on state %s\n", |
561 | sta->sta.addr, mplstates[sta->plink_state]); | 580 | sta->sta.addr, mplstates[sta->plink_state]); |
@@ -773,9 +792,7 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, | |||
773 | break; | 792 | break; |
774 | case CNF_ACPT: | 793 | case CNF_ACPT: |
775 | sta->plink_state = NL80211_PLINK_CNF_RCVD; | 794 | sta->plink_state = NL80211_PLINK_CNF_RCVD; |
776 | if (!mod_plink_timer(sta, | 795 | mod_plink_timer(sta, mshcfg->dot11MeshConfirmTimeout); |
777 | mshcfg->dot11MeshConfirmTimeout)) | ||
778 | sta->ignore_plink_timer = true; | ||
779 | break; | 796 | break; |
780 | default: | 797 | default: |
781 | break; | 798 | break; |
@@ -834,8 +851,7 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, | |||
834 | case NL80211_PLINK_HOLDING: | 851 | case NL80211_PLINK_HOLDING: |
835 | switch (event) { | 852 | switch (event) { |
836 | case CLS_ACPT: | 853 | case CLS_ACPT: |
837 | if (del_timer(&sta->plink_timer)) | 854 | del_timer(&sta->plink_timer); |
838 | sta->ignore_plink_timer = 1; | ||
839 | mesh_plink_fsm_restart(sta); | 855 | mesh_plink_fsm_restart(sta); |
840 | break; | 856 | break; |
841 | case OPN_ACPT: | 857 | case OPN_ACPT: |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index dee0b645b34c..159cac903ce8 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -306,7 +306,6 @@ struct ieee80211_tx_latency_stat { | |||
306 | * @plid: Peer link ID | 306 | * @plid: Peer link ID |
307 | * @reason: Cancel reason on PLINK_HOLDING state | 307 | * @reason: Cancel reason on PLINK_HOLDING state |
308 | * @plink_retries: Retries in establishment | 308 | * @plink_retries: Retries in establishment |
309 | * @ignore_plink_timer: ignore the peer-link timer (used internally) | ||
310 | * @plink_state: peer link state | 309 | * @plink_state: peer link state |
311 | * @plink_timeout: timeout of peer link | 310 | * @plink_timeout: timeout of peer link |
312 | * @plink_timer: peer link watch timer | 311 | * @plink_timer: peer link watch timer |
@@ -421,7 +420,6 @@ struct sta_info { | |||
421 | u16 plid; | 420 | u16 plid; |
422 | u16 reason; | 421 | u16 reason; |
423 | u8 plink_retries; | 422 | u8 plink_retries; |
424 | bool ignore_plink_timer; | ||
425 | enum nl80211_plink_state plink_state; | 423 | enum nl80211_plink_state plink_state; |
426 | u32 plink_timeout; | 424 | u32 plink_timeout; |
427 | struct timer_list plink_timer; | 425 | struct timer_list plink_timer; |