aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh_pathtbl.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mesh_pathtbl.c')
-rw-r--r--net/mac80211/mesh_pathtbl.c151
1 files changed, 115 insertions, 36 deletions
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 04b9e4d61b8e..751c4d0e2b36 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -38,6 +38,71 @@ struct mpath_node {
38static struct mesh_table *mesh_paths; 38static struct mesh_table *mesh_paths;
39static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ 39static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */
40 40
41int mesh_paths_generation;
42static void __mesh_table_free(struct mesh_table *tbl)
43{
44 kfree(tbl->hash_buckets);
45 kfree(tbl->hashwlock);
46 kfree(tbl);
47}
48
49void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
50{
51 struct hlist_head *mesh_hash;
52 struct hlist_node *p, *q;
53 int i;
54
55 mesh_hash = tbl->hash_buckets;
56 for (i = 0; i <= tbl->hash_mask; i++) {
57 spin_lock(&tbl->hashwlock[i]);
58 hlist_for_each_safe(p, q, &mesh_hash[i]) {
59 tbl->free_node(p, free_leafs);
60 atomic_dec(&tbl->entries);
61 }
62 spin_unlock(&tbl->hashwlock[i]);
63 }
64 __mesh_table_free(tbl);
65}
66
67static struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
68{
69 struct mesh_table *newtbl;
70 struct hlist_head *oldhash;
71 struct hlist_node *p, *q;
72 int i;
73
74 if (atomic_read(&tbl->entries)
75 < tbl->mean_chain_len * (tbl->hash_mask + 1))
76 goto endgrow;
77
78 newtbl = mesh_table_alloc(tbl->size_order + 1);
79 if (!newtbl)
80 goto endgrow;
81
82 newtbl->free_node = tbl->free_node;
83 newtbl->mean_chain_len = tbl->mean_chain_len;
84 newtbl->copy_node = tbl->copy_node;
85 atomic_set(&newtbl->entries, atomic_read(&tbl->entries));
86
87 oldhash = tbl->hash_buckets;
88 for (i = 0; i <= tbl->hash_mask; i++)
89 hlist_for_each(p, &oldhash[i])
90 if (tbl->copy_node(p, newtbl) < 0)
91 goto errcopy;
92
93 return newtbl;
94
95errcopy:
96 for (i = 0; i <= newtbl->hash_mask; i++) {
97 hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
98 tbl->free_node(p, 0);
99 }
100 __mesh_table_free(newtbl);
101endgrow:
102 return NULL;
103}
104
105
41/* This lock will have the grow table function as writer and add / delete nodes 106/* This lock will have the grow table function as writer and add / delete nodes
42 * as readers. When reading the table (i.e. doing lookups) we are well protected 107 * as readers. When reading the table (i.e. doing lookups) we are well protected
43 * by RCU 108 * by RCU
@@ -185,6 +250,8 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data
185 */ 250 */
186int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) 251int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
187{ 252{
253 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
254 struct ieee80211_local *local = sdata->local;
188 struct mesh_path *mpath, *new_mpath; 255 struct mesh_path *mpath, *new_mpath;
189 struct mpath_node *node, *new_node; 256 struct mpath_node *node, *new_node;
190 struct hlist_head *bucket; 257 struct hlist_head *bucket;
@@ -193,8 +260,6 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
193 int err = 0; 260 int err = 0;
194 u32 hash_idx; 261 u32 hash_idx;
195 262
196 might_sleep();
197
198 if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) 263 if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
199 /* never add ourselves as neighbours */ 264 /* never add ourselves as neighbours */
200 return -ENOTSUPP; 265 return -ENOTSUPP;
@@ -206,11 +271,11 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
206 return -ENOSPC; 271 return -ENOSPC;
207 272
208 err = -ENOMEM; 273 err = -ENOMEM;
209 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); 274 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
210 if (!new_mpath) 275 if (!new_mpath)
211 goto err_path_alloc; 276 goto err_path_alloc;
212 277
213 new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); 278 new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
214 if (!new_node) 279 if (!new_node)
215 goto err_node_alloc; 280 goto err_node_alloc;
216 281
@@ -243,23 +308,13 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
243 mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1)) 308 mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1))
244 grow = 1; 309 grow = 1;
245 310
311 mesh_paths_generation++;
312
246 spin_unlock(&mesh_paths->hashwlock[hash_idx]); 313 spin_unlock(&mesh_paths->hashwlock[hash_idx]);
247 read_unlock(&pathtbl_resize_lock); 314 read_unlock(&pathtbl_resize_lock);
248 if (grow) { 315 if (grow) {
249 struct mesh_table *oldtbl, *newtbl; 316 set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
250 317 ieee80211_queue_work(&local->hw, &ifmsh->work);
251 write_lock(&pathtbl_resize_lock);
252 oldtbl = mesh_paths;
253 newtbl = mesh_table_grow(mesh_paths);
254 if (!newtbl) {
255 write_unlock(&pathtbl_resize_lock);
256 return 0;
257 }
258 rcu_assign_pointer(mesh_paths, newtbl);
259 write_unlock(&pathtbl_resize_lock);
260
261 synchronize_rcu();
262 mesh_table_free(oldtbl, false);
263 } 318 }
264 return 0; 319 return 0;
265 320
@@ -274,9 +329,46 @@ err_path_alloc:
274 return err; 329 return err;
275} 330}
276 331
332void mesh_mpath_table_grow(void)
333{
334 struct mesh_table *oldtbl, *newtbl;
335
336 write_lock(&pathtbl_resize_lock);
337 oldtbl = mesh_paths;
338 newtbl = mesh_table_grow(mesh_paths);
339 if (!newtbl) {
340 write_unlock(&pathtbl_resize_lock);
341 return;
342 }
343 rcu_assign_pointer(mesh_paths, newtbl);
344 write_unlock(&pathtbl_resize_lock);
345
346 synchronize_rcu();
347 mesh_table_free(oldtbl, false);
348}
349
350void mesh_mpp_table_grow(void)
351{
352 struct mesh_table *oldtbl, *newtbl;
353
354 write_lock(&pathtbl_resize_lock);
355 oldtbl = mpp_paths;
356 newtbl = mesh_table_grow(mpp_paths);
357 if (!newtbl) {
358 write_unlock(&pathtbl_resize_lock);
359 return;
360 }
361 rcu_assign_pointer(mpp_paths, newtbl);
362 write_unlock(&pathtbl_resize_lock);
363
364 synchronize_rcu();
365 mesh_table_free(oldtbl, false);
366}
277 367
278int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) 368int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
279{ 369{
370 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
371 struct ieee80211_local *local = sdata->local;
280 struct mesh_path *mpath, *new_mpath; 372 struct mesh_path *mpath, *new_mpath;
281 struct mpath_node *node, *new_node; 373 struct mpath_node *node, *new_node;
282 struct hlist_head *bucket; 374 struct hlist_head *bucket;
@@ -285,8 +377,6 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
285 int err = 0; 377 int err = 0;
286 u32 hash_idx; 378 u32 hash_idx;
287 379
288 might_sleep();
289
290 if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) 380 if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
291 /* never add ourselves as neighbours */ 381 /* never add ourselves as neighbours */
292 return -ENOTSUPP; 382 return -ENOTSUPP;
@@ -295,11 +385,11 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
295 return -ENOTSUPP; 385 return -ENOTSUPP;
296 386
297 err = -ENOMEM; 387 err = -ENOMEM;
298 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); 388 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
299 if (!new_mpath) 389 if (!new_mpath)
300 goto err_path_alloc; 390 goto err_path_alloc;
301 391
302 new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); 392 new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
303 if (!new_node) 393 if (!new_node)
304 goto err_node_alloc; 394 goto err_node_alloc;
305 395
@@ -333,20 +423,8 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
333 spin_unlock(&mpp_paths->hashwlock[hash_idx]); 423 spin_unlock(&mpp_paths->hashwlock[hash_idx]);
334 read_unlock(&pathtbl_resize_lock); 424 read_unlock(&pathtbl_resize_lock);
335 if (grow) { 425 if (grow) {
336 struct mesh_table *oldtbl, *newtbl; 426 set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags);
337 427 ieee80211_queue_work(&local->hw, &ifmsh->work);
338 write_lock(&pathtbl_resize_lock);
339 oldtbl = mpp_paths;
340 newtbl = mesh_table_grow(mpp_paths);
341 if (!newtbl) {
342 write_unlock(&pathtbl_resize_lock);
343 return 0;
344 }
345 rcu_assign_pointer(mpp_paths, newtbl);
346 write_unlock(&pathtbl_resize_lock);
347
348 synchronize_rcu();
349 mesh_table_free(oldtbl, false);
350 } 428 }
351 return 0; 429 return 0;
352 430
@@ -484,6 +562,7 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
484 562
485 err = -ENXIO; 563 err = -ENXIO;
486enddel: 564enddel:
565 mesh_paths_generation++;
487 spin_unlock(&mesh_paths->hashwlock[hash_idx]); 566 spin_unlock(&mesh_paths->hashwlock[hash_idx]);
488 read_unlock(&pathtbl_resize_lock); 567 read_unlock(&pathtbl_resize_lock);
489 return err; 568 return err;