aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/mesh_plink.c30
-rw-r--r--net/mac80211/sta_info.h2
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;