diff mbox

mac80211: fix mesh sta teardown

Message ID 1360137925-14264-1-git-send-email-thomas@cozybit.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Thomas Pedersen Feb. 6, 2013, 8:05 a.m. UTC
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 <thomas@cozybit.com>
---
 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(-)

Comments

Thomas Pedersen Feb. 6, 2013, 8:26 a.m. UTC | #1
On Wed, Feb 6, 2013 at 12:05 AM, Thomas Pedersen <thomas@cozybit.com> wrote:
> 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.

Wait, this would also apply to the del_timer_sync() in
mesh_plink_quiesce() then. v2 will add this check to that function.
diff mbox

Patch

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);