aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/cfg.c2
-rw-r--r--net/mac80211/iface.c6
-rw-r--r--net/mac80211/mesh.h2
-rw-r--r--net/mac80211/mesh_pathtbl.c40
4 files changed, 47 insertions, 3 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 0baaaecf455..5c0d8fab0e8 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -921,7 +921,7 @@ static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
921 if (dst) 921 if (dst)
922 return mesh_path_del(dst, sdata); 922 return mesh_path_del(dst, sdata);
923 923
924 mesh_path_flush(sdata); 924 mesh_path_flush_by_iface(sdata);
925 return 0; 925 return 0;
926} 926}
927 927
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 556e7e6ddf0..eaa80a3d412 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1214,6 +1214,9 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata)
1214 list_del_rcu(&sdata->list); 1214 list_del_rcu(&sdata->list);
1215 mutex_unlock(&sdata->local->iflist_mtx); 1215 mutex_unlock(&sdata->local->iflist_mtx);
1216 1216
1217 if (ieee80211_vif_is_mesh(&sdata->vif))
1218 mesh_path_flush_by_iface(sdata);
1219
1217 synchronize_rcu(); 1220 synchronize_rcu();
1218 unregister_netdevice(sdata->dev); 1221 unregister_netdevice(sdata->dev);
1219} 1222}
@@ -1233,6 +1236,9 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
1233 list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { 1236 list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
1234 list_del(&sdata->list); 1237 list_del(&sdata->list);
1235 1238
1239 if (ieee80211_vif_is_mesh(&sdata->vif))
1240 mesh_path_flush_by_iface(sdata);
1241
1236 unregister_netdevice_queue(sdata->dev, &unreg_list); 1242 unregister_netdevice_queue(sdata->dev, &unreg_list);
1237 } 1243 }
1238 mutex_unlock(&local->iflist_mtx); 1244 mutex_unlock(&local->iflist_mtx);
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 20272072171..57a2ad021be 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -238,7 +238,6 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx,
238 struct ieee80211_sub_if_data *sdata); 238 struct ieee80211_sub_if_data *sdata);
239void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); 239void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
240void mesh_path_expire(struct ieee80211_sub_if_data *sdata); 240void mesh_path_expire(struct ieee80211_sub_if_data *sdata);
241void mesh_path_flush(struct ieee80211_sub_if_data *sdata);
242void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, 241void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
243 struct ieee80211_mgmt *mgmt, size_t len); 242 struct ieee80211_mgmt *mgmt, size_t len);
244int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); 243int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata);
@@ -275,6 +274,7 @@ void mesh_pathtbl_unregister(void);
275int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata); 274int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata);
276void mesh_path_timer(unsigned long data); 275void mesh_path_timer(unsigned long data);
277void mesh_path_flush_by_nexthop(struct sta_info *sta); 276void mesh_path_flush_by_nexthop(struct sta_info *sta);
277void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata);
278void mesh_path_discard_frame(struct sk_buff *skb, 278void mesh_path_discard_frame(struct sk_buff *skb,
279 struct ieee80211_sub_if_data *sdata); 279 struct ieee80211_sub_if_data *sdata);
280void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); 280void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 2218eaf48bc..d07279911a0 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -821,7 +821,7 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
821 rcu_read_unlock(); 821 rcu_read_unlock();
822} 822}
823 823
824void mesh_path_flush(struct ieee80211_sub_if_data *sdata) 824static void mesh_path_flush(struct ieee80211_sub_if_data *sdata)
825{ 825{
826 struct mesh_table *tbl; 826 struct mesh_table *tbl;
827 struct mesh_path *mpath; 827 struct mesh_path *mpath;
@@ -850,6 +850,44 @@ static void mesh_path_node_reclaim(struct rcu_head *rp)
850 kfree(node); 850 kfree(node);
851} 851}
852 852
853static void mpp_path_flush(struct ieee80211_sub_if_data *sdata)
854{
855 struct mesh_table *tbl;
856 struct mesh_path *mpath;
857 struct mpath_node *node;
858 struct hlist_node *p;
859 int i;
860
861 read_lock_bh(&pathtbl_resize_lock);
862 tbl = rcu_dereference_protected(mpp_paths,
863 lockdep_is_held(pathtbl_resize_lock));
864 for_each_mesh_entry(tbl, p, node, i) {
865 mpath = node->mpath;
866 if (mpath->sdata != sdata)
867 continue;
868 spin_lock_bh(&tbl->hashwlock[i]);
869 spin_lock_bh(&mpath->state_lock);
870 call_rcu(&node->rcu, mesh_path_node_reclaim);
871 atomic_dec(&tbl->entries);
872 spin_unlock_bh(&tbl->hashwlock[i]);
873 }
874 read_unlock_bh(&pathtbl_resize_lock);
875}
876
877/**
878 * mesh_path_flush_by_iface - Deletes all mesh paths associated with a given iface
879 *
880 * This function deletes both mesh paths as well as mesh portal paths.
881 *
882 * @sdata - interface data to match
883 *
884 */
885void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
886{
887 mesh_path_flush(sdata);
888 mpp_path_flush(sdata);
889}
890
853/** 891/**
854 * mesh_path_del - delete a mesh path from the table 892 * mesh_path_del - delete a mesh path from the table
855 * 893 *