The patch "mac80211: clean up mesh sta allocation warning"
moved some mesh initialization into a path which is only
called when the kernel handles peering. This causes a hang
when mac80211 tries to clean up a userspace-allocated
station entry and delete a timer which has never been
initialized.

To avoid this, only do any mesh sta peering teardown if
the kernel is actually handling it.

Signed-off-by: Thomas Pedersen <[email protected]>
---
 net/mac80211/mesh.c       |   25 +++++++++++++++++++++++++
 net/mac80211/mesh.h       |    4 +++-
 net/mac80211/mesh_plink.c |    4 ++--
 net/mac80211/sta_info.c   |    9 ++-------
 4 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 35ac388..0c51b78 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -149,6 +149,31 @@ u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data 
*sdata)
        return changed;
 }
 
+/*
+ * mesh_sta_cleanup - clean up any mesh sta state
+ *
+ * @sta: mesh sta to clean up.
+ */
+void mesh_sta_cleanup(struct sta_info *sta)
+{
+       struct ieee80211_sub_if_data *sdata = sta->sdata;
+       u32 changed;
+
+       /*
+        * maybe userspace handles peer allocation and peering, but in either
+        * case the beacon is still generated by the kernel and we might need
+        * an update.
+        */
+       changed = mesh_accept_plinks_update(sdata);
+       if (sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
+               changed |= mesh_plink_deactivate(sta);
+               del_timer_sync(&sta->plink_timer);
+       }
+
+       if (changed)
+               ieee80211_bss_info_change_notify(sdata, changed);
+}
+
 int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
 {
        int i;
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index eb33625..e5f6095 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -288,12 +288,13 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data 
*sdata,
 bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie);
 u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
 void mesh_plink_broken(struct sta_info *sta);
-void mesh_plink_deactivate(struct sta_info *sta);
+u32 mesh_plink_deactivate(struct sta_info *sta);
 int mesh_plink_open(struct sta_info *sta);
 void mesh_plink_block(struct sta_info *sta);
 void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
                         struct ieee80211_mgmt *mgmt, size_t len,
                         struct ieee80211_rx_status *rx_status);
+void mesh_sta_cleanup(struct sta_info *sta);
 
 /* Private interfaces */
 /* Mesh tables */
@@ -380,6 +381,7 @@ static inline bool mesh_path_sel_is_hwmp(struct 
ieee80211_sub_if_data *sdata)
 { return false; }
 static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data 
*sdata)
 {}
+static inline void mesh_sta_cleanup(struct sta_info *sta) {}
 #endif
 
 #endif /* IEEE80211S_H */
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 67524e7..cdf66fb 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -214,7 +214,7 @@ static u32 __mesh_plink_deactivate(struct sta_info *sta)
  *
  * All mesh paths with this peer as next hop will be flushed
  */
-void mesh_plink_deactivate(struct sta_info *sta)
+u32 mesh_plink_deactivate(struct sta_info *sta)
 {
        struct ieee80211_sub_if_data *sdata = sta->sdata;
        u32 changed;
@@ -227,7 +227,7 @@ void mesh_plink_deactivate(struct sta_info *sta)
                            sta->reason);
        spin_unlock_bh(&sta->lock);
 
-       ieee80211_bss_info_change_notify(sdata, changed);
+       return changed;
 }
 
 static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 47a0f06..19db20a 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -137,13 +137,8 @@ static void cleanup_single_sta(struct sta_info *sta)
                ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]);
        }
 
-#ifdef CONFIG_MAC80211_MESH
-       if (ieee80211_vif_is_mesh(&sdata->vif)) {
-               mesh_accept_plinks_update(sdata);
-               mesh_plink_deactivate(sta);
-               del_timer_sync(&sta->plink_timer);
-       }
-#endif
+       if (ieee80211_vif_is_mesh(&sdata->vif))
+               mesh_sta_cleanup(sta);
 
        cancel_work_sync(&sta->drv_unblock_wk);
 
-- 
1.7.10.4

_______________________________________________
Devel mailing list
[email protected]
http://lists.open80211s.org/cgi-bin/mailman/listinfo/devel

Reply via email to