diff options
Diffstat (limited to 'net/mac80211/mesh_plink.c')
-rw-r--r-- | net/mac80211/mesh_plink.c | 101 |
1 files changed, 52 insertions, 49 deletions
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index b5fbe970e48f..c2b80500ae72 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -65,14 +65,14 @@ static inline | |||
65 | void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) | 65 | void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) |
66 | { | 66 | { |
67 | atomic_inc(&sdata->u.sta.mshstats.estab_plinks); | 67 | atomic_inc(&sdata->u.sta.mshstats.estab_plinks); |
68 | mesh_accept_plinks_update(sdata->dev); | 68 | mesh_accept_plinks_update(sdata); |
69 | } | 69 | } |
70 | 70 | ||
71 | static inline | 71 | static inline |
72 | void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) | 72 | void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) |
73 | { | 73 | { |
74 | atomic_dec(&sdata->u.sta.mshstats.estab_plinks); | 74 | atomic_dec(&sdata->u.sta.mshstats.estab_plinks); |
75 | mesh_accept_plinks_update(sdata->dev); | 75 | mesh_accept_plinks_update(sdata); |
76 | } | 76 | } |
77 | 77 | ||
78 | /** | 78 | /** |
@@ -99,12 +99,13 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta) | |||
99 | * | 99 | * |
100 | * Returns: non-NULL on success, ERR_PTR() on error. | 100 | * Returns: non-NULL on success, ERR_PTR() on error. |
101 | */ | 101 | */ |
102 | struct sta_info *mesh_plink_add(u8 *hw_addr, u64 rates, struct net_device *dev) | 102 | struct sta_info *mesh_plink_add(u8 *hw_addr, u64 rates, |
103 | struct ieee80211_sub_if_data *sdata) | ||
103 | { | 104 | { |
104 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 105 | struct ieee80211_local *local = sdata->local; |
105 | struct sta_info *sta; | 106 | struct sta_info *sta; |
106 | 107 | ||
107 | if (memcmp(hw_addr, dev->dev_addr, ETH_ALEN) == 0) | 108 | if (compare_ether_addr(hw_addr, sdata->dev->dev_addr) == 0) |
108 | /* never add ourselves as neighbours */ | 109 | /* never add ourselves as neighbours */ |
109 | return ERR_PTR(-EINVAL); | 110 | return ERR_PTR(-EINVAL); |
110 | 111 | ||
@@ -114,7 +115,7 @@ struct sta_info *mesh_plink_add(u8 *hw_addr, u64 rates, struct net_device *dev) | |||
114 | if (local->num_sta >= MESH_MAX_PLINKS) | 115 | if (local->num_sta >= MESH_MAX_PLINKS) |
115 | return ERR_PTR(-ENOSPC); | 116 | return ERR_PTR(-ENOSPC); |
116 | 117 | ||
117 | sta = sta_info_add(local, dev, hw_addr, GFP_KERNEL); | 118 | sta = sta_info_add(sdata, hw_addr); |
118 | if (IS_ERR(sta)) | 119 | if (IS_ERR(sta)) |
119 | return sta; | 120 | return sta; |
120 | 121 | ||
@@ -125,7 +126,7 @@ struct sta_info *mesh_plink_add(u8 *hw_addr, u64 rates, struct net_device *dev) | |||
125 | sta->supp_rates[local->hw.conf.channel->band] = rates; | 126 | sta->supp_rates[local->hw.conf.channel->band] = rates; |
126 | rate_control_rate_init(sta, local); | 127 | rate_control_rate_init(sta, local); |
127 | 128 | ||
128 | mesh_accept_plinks_update(dev); | 129 | mesh_accept_plinks_update(sdata); |
129 | 130 | ||
130 | return sta; | 131 | return sta; |
131 | } | 132 | } |
@@ -141,7 +142,8 @@ struct sta_info *mesh_plink_add(u8 *hw_addr, u64 rates, struct net_device *dev) | |||
141 | */ | 142 | */ |
142 | static void __mesh_plink_deactivate(struct sta_info *sta) | 143 | static void __mesh_plink_deactivate(struct sta_info *sta) |
143 | { | 144 | { |
144 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | 145 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
146 | |||
145 | if (sta->plink_state == ESTAB) | 147 | if (sta->plink_state == ESTAB) |
146 | mesh_plink_dec_estab_count(sdata); | 148 | mesh_plink_dec_estab_count(sdata); |
147 | sta->plink_state = BLOCKED; | 149 | sta->plink_state = BLOCKED; |
@@ -246,11 +248,15 @@ void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev, | |||
246 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 248 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
247 | struct sta_info *sta; | 249 | struct sta_info *sta; |
248 | 250 | ||
251 | rcu_read_lock(); | ||
252 | |||
249 | sta = sta_info_get(local, hw_addr); | 253 | sta = sta_info_get(local, hw_addr); |
250 | if (!sta) { | 254 | if (!sta) { |
251 | sta = mesh_plink_add(hw_addr, rates, dev); | 255 | sta = mesh_plink_add(hw_addr, rates, sdata); |
252 | if (IS_ERR(sta)) | 256 | if (IS_ERR(sta)) { |
257 | rcu_read_unlock(); | ||
253 | return; | 258 | return; |
259 | } | ||
254 | } | 260 | } |
255 | 261 | ||
256 | sta->last_rx = jiffies; | 262 | sta->last_rx = jiffies; |
@@ -260,7 +266,7 @@ void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev, | |||
260 | sdata->u.sta.mshcfg.auto_open_plinks) | 266 | sdata->u.sta.mshcfg.auto_open_plinks) |
261 | mesh_plink_open(sta); | 267 | mesh_plink_open(sta); |
262 | 268 | ||
263 | sta_info_put(sta); | 269 | rcu_read_unlock(); |
264 | } | 270 | } |
265 | 271 | ||
266 | static void mesh_plink_timer(unsigned long data) | 272 | static void mesh_plink_timer(unsigned long data) |
@@ -273,6 +279,11 @@ static void mesh_plink_timer(unsigned long data) | |||
273 | DECLARE_MAC_BUF(mac); | 279 | DECLARE_MAC_BUF(mac); |
274 | #endif | 280 | #endif |
275 | 281 | ||
282 | /* | ||
283 | * This STA is valid because sta_info_destroy() will | ||
284 | * del_timer_sync() this timer after having made sure | ||
285 | * it cannot be readded (by deleting the plink.) | ||
286 | */ | ||
276 | sta = (struct sta_info *) data; | 287 | sta = (struct sta_info *) data; |
277 | 288 | ||
278 | spin_lock_bh(&sta->plink_lock); | 289 | spin_lock_bh(&sta->plink_lock); |
@@ -286,8 +297,8 @@ static void mesh_plink_timer(unsigned long data) | |||
286 | reason = 0; | 297 | reason = 0; |
287 | llid = sta->llid; | 298 | llid = sta->llid; |
288 | plid = sta->plid; | 299 | plid = sta->plid; |
289 | dev = sta->dev; | 300 | sdata = sta->sdata; |
290 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 301 | dev = sdata->dev; |
291 | 302 | ||
292 | switch (sta->plink_state) { | 303 | switch (sta->plink_state) { |
293 | case OPN_RCVD: | 304 | case OPN_RCVD: |
@@ -302,8 +313,7 @@ static void mesh_plink_timer(unsigned long data) | |||
302 | sta->plink_timeout = sta->plink_timeout + | 313 | sta->plink_timeout = sta->plink_timeout + |
303 | rand % sta->plink_timeout; | 314 | rand % sta->plink_timeout; |
304 | ++sta->plink_retries; | 315 | ++sta->plink_retries; |
305 | if (!mod_plink_timer(sta, sta->plink_timeout)) | 316 | mod_plink_timer(sta, sta->plink_timeout); |
306 | __sta_info_get(sta); | ||
307 | spin_unlock_bh(&sta->plink_lock); | 317 | spin_unlock_bh(&sta->plink_lock); |
308 | mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, | 318 | mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, |
309 | 0, 0); | 319 | 0, 0); |
@@ -316,16 +326,14 @@ static void mesh_plink_timer(unsigned long data) | |||
316 | if (!reason) | 326 | if (!reason) |
317 | reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT); | 327 | reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT); |
318 | sta->plink_state = HOLDING; | 328 | sta->plink_state = HOLDING; |
319 | if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata))) | 329 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
320 | __sta_info_get(sta); | ||
321 | spin_unlock_bh(&sta->plink_lock); | 330 | spin_unlock_bh(&sta->plink_lock); |
322 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid, | 331 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid, |
323 | reason); | 332 | reason); |
324 | break; | 333 | break; |
325 | case HOLDING: | 334 | case HOLDING: |
326 | /* holding timer */ | 335 | /* holding timer */ |
327 | if (del_timer(&sta->plink_timer)) | 336 | del_timer(&sta->plink_timer); |
328 | sta_info_put(sta); | ||
329 | mesh_plink_fsm_restart(sta); | 337 | mesh_plink_fsm_restart(sta); |
330 | spin_unlock_bh(&sta->plink_lock); | 338 | spin_unlock_bh(&sta->plink_lock); |
331 | break; | 339 | break; |
@@ -333,8 +341,6 @@ static void mesh_plink_timer(unsigned long data) | |||
333 | spin_unlock_bh(&sta->plink_lock); | 341 | spin_unlock_bh(&sta->plink_lock); |
334 | break; | 342 | break; |
335 | } | 343 | } |
336 | |||
337 | sta_info_put(sta); | ||
338 | } | 344 | } |
339 | 345 | ||
340 | static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) | 346 | static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) |
@@ -343,14 +349,13 @@ static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) | |||
343 | sta->plink_timer.data = (unsigned long) sta; | 349 | sta->plink_timer.data = (unsigned long) sta; |
344 | sta->plink_timer.function = mesh_plink_timer; | 350 | sta->plink_timer.function = mesh_plink_timer; |
345 | sta->plink_timeout = timeout; | 351 | sta->plink_timeout = timeout; |
346 | __sta_info_get(sta); | ||
347 | add_timer(&sta->plink_timer); | 352 | add_timer(&sta->plink_timer); |
348 | } | 353 | } |
349 | 354 | ||
350 | int mesh_plink_open(struct sta_info *sta) | 355 | int mesh_plink_open(struct sta_info *sta) |
351 | { | 356 | { |
352 | __le16 llid; | 357 | __le16 llid; |
353 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | 358 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
354 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG | 359 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG |
355 | DECLARE_MAC_BUF(mac); | 360 | DECLARE_MAC_BUF(mac); |
356 | #endif | 361 | #endif |
@@ -360,7 +365,6 @@ int mesh_plink_open(struct sta_info *sta) | |||
360 | sta->llid = llid; | 365 | sta->llid = llid; |
361 | if (sta->plink_state != LISTEN) { | 366 | if (sta->plink_state != LISTEN) { |
362 | spin_unlock_bh(&sta->plink_lock); | 367 | spin_unlock_bh(&sta->plink_lock); |
363 | sta_info_put(sta); | ||
364 | return -EBUSY; | 368 | return -EBUSY; |
365 | } | 369 | } |
366 | sta->plink_state = OPN_SNT; | 370 | sta->plink_state = OPN_SNT; |
@@ -369,7 +373,8 @@ int mesh_plink_open(struct sta_info *sta) | |||
369 | mpl_dbg("Mesh plink: starting establishment with %s\n", | 373 | mpl_dbg("Mesh plink: starting establishment with %s\n", |
370 | print_mac(mac, sta->addr)); | 374 | print_mac(mac, sta->addr)); |
371 | 375 | ||
372 | return mesh_plink_frame_tx(sta->dev, PLINK_OPEN, sta->addr, llid, 0, 0); | 376 | return mesh_plink_frame_tx(sdata->dev, PLINK_OPEN, |
377 | sta->addr, llid, 0, 0); | ||
373 | } | 378 | } |
374 | 379 | ||
375 | void mesh_plink_block(struct sta_info *sta) | 380 | void mesh_plink_block(struct sta_info *sta) |
@@ -386,7 +391,7 @@ void mesh_plink_block(struct sta_info *sta) | |||
386 | 391 | ||
387 | int mesh_plink_close(struct sta_info *sta) | 392 | int mesh_plink_close(struct sta_info *sta) |
388 | { | 393 | { |
389 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | 394 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
390 | int llid, plid, reason; | 395 | int llid, plid, reason; |
391 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG | 396 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG |
392 | DECLARE_MAC_BUF(mac); | 397 | DECLARE_MAC_BUF(mac); |
@@ -401,13 +406,11 @@ int mesh_plink_close(struct sta_info *sta) | |||
401 | if (sta->plink_state == LISTEN || sta->plink_state == BLOCKED) { | 406 | if (sta->plink_state == LISTEN || sta->plink_state == BLOCKED) { |
402 | mesh_plink_fsm_restart(sta); | 407 | mesh_plink_fsm_restart(sta); |
403 | spin_unlock_bh(&sta->plink_lock); | 408 | spin_unlock_bh(&sta->plink_lock); |
404 | sta_info_put(sta); | ||
405 | return 0; | 409 | return 0; |
406 | } else if (sta->plink_state == ESTAB) { | 410 | } else if (sta->plink_state == ESTAB) { |
407 | __mesh_plink_deactivate(sta); | 411 | __mesh_plink_deactivate(sta); |
408 | /* The timer should not be running */ | 412 | /* The timer should not be running */ |
409 | if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata))) | 413 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
410 | __sta_info_get(sta); | ||
411 | } else if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata))) | 414 | } else if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata))) |
412 | sta->ignore_plink_timer = true; | 415 | sta->ignore_plink_timer = true; |
413 | 416 | ||
@@ -415,15 +418,16 @@ int mesh_plink_close(struct sta_info *sta) | |||
415 | llid = sta->llid; | 418 | llid = sta->llid; |
416 | plid = sta->plid; | 419 | plid = sta->plid; |
417 | spin_unlock_bh(&sta->plink_lock); | 420 | spin_unlock_bh(&sta->plink_lock); |
418 | mesh_plink_frame_tx(sta->dev, PLINK_CLOSE, sta->addr, llid, plid, | 421 | mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid, |
419 | reason); | 422 | plid, reason); |
420 | return 0; | 423 | return 0; |
421 | } | 424 | } |
422 | 425 | ||
423 | void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | 426 | void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, |
424 | size_t len, struct ieee80211_rx_status *rx_status) | 427 | size_t len, struct ieee80211_rx_status *rx_status) |
425 | { | 428 | { |
426 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 429 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
430 | struct ieee80211_local *local = sdata->local; | ||
427 | struct ieee802_11_elems elems; | 431 | struct ieee802_11_elems elems; |
428 | struct sta_info *sta; | 432 | struct sta_info *sta; |
429 | enum plink_event event; | 433 | enum plink_event event; |
@@ -435,7 +439,6 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
435 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG | 439 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG |
436 | DECLARE_MAC_BUF(mac); | 440 | DECLARE_MAC_BUF(mac); |
437 | #endif | 441 | #endif |
438 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
439 | 442 | ||
440 | if (is_multicast_ether_addr(mgmt->da)) { | 443 | if (is_multicast_ether_addr(mgmt->da)) { |
441 | mpl_dbg("Mesh plink: ignore frame from multicast address"); | 444 | mpl_dbg("Mesh plink: ignore frame from multicast address"); |
@@ -474,14 +477,17 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
474 | if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 7)) | 477 | if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 7)) |
475 | memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2); | 478 | memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2); |
476 | 479 | ||
480 | rcu_read_lock(); | ||
481 | |||
477 | sta = sta_info_get(local, mgmt->sa); | 482 | sta = sta_info_get(local, mgmt->sa); |
478 | if (!sta && ftype != PLINK_OPEN) { | 483 | if (!sta && ftype != PLINK_OPEN) { |
479 | mpl_dbg("Mesh plink: cls or cnf from unknown peer\n"); | 484 | mpl_dbg("Mesh plink: cls or cnf from unknown peer\n"); |
485 | rcu_read_unlock(); | ||
480 | return; | 486 | return; |
481 | } | 487 | } |
482 | 488 | ||
483 | if (sta && sta->plink_state == BLOCKED) { | 489 | if (sta && sta->plink_state == BLOCKED) { |
484 | sta_info_put(sta); | 490 | rcu_read_unlock(); |
485 | return; | 491 | return; |
486 | } | 492 | } |
487 | 493 | ||
@@ -505,13 +511,15 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
505 | u64 rates; | 511 | u64 rates; |
506 | if (!mesh_plink_free_count(sdata)) { | 512 | if (!mesh_plink_free_count(sdata)) { |
507 | mpl_dbg("Mesh plink error: no more free plinks\n"); | 513 | mpl_dbg("Mesh plink error: no more free plinks\n"); |
514 | rcu_read_unlock(); | ||
508 | return; | 515 | return; |
509 | } | 516 | } |
510 | 517 | ||
511 | rates = ieee80211_sta_get_rates(local, &elems, rx_status->band); | 518 | rates = ieee80211_sta_get_rates(local, &elems, rx_status->band); |
512 | sta = mesh_plink_add(mgmt->sa, rates, dev); | 519 | sta = mesh_plink_add(mgmt->sa, rates, sdata); |
513 | if (IS_ERR(sta)) { | 520 | if (IS_ERR(sta)) { |
514 | mpl_dbg("Mesh plink error: plink table full\n"); | 521 | mpl_dbg("Mesh plink error: plink table full\n"); |
522 | rcu_read_unlock(); | ||
515 | return; | 523 | return; |
516 | } | 524 | } |
517 | event = OPN_ACPT; | 525 | event = OPN_ACPT; |
@@ -521,14 +529,14 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
521 | switch (ftype) { | 529 | switch (ftype) { |
522 | case PLINK_OPEN: | 530 | case PLINK_OPEN: |
523 | if (!mesh_plink_free_count(sdata) || | 531 | if (!mesh_plink_free_count(sdata) || |
524 | (sta->plid && sta->plid != plid)) | 532 | (sta->plid && sta->plid != plid)) |
525 | event = OPN_IGNR; | 533 | event = OPN_IGNR; |
526 | else | 534 | else |
527 | event = OPN_ACPT; | 535 | event = OPN_ACPT; |
528 | break; | 536 | break; |
529 | case PLINK_CONFIRM: | 537 | case PLINK_CONFIRM: |
530 | if (!mesh_plink_free_count(sdata) || | 538 | if (!mesh_plink_free_count(sdata) || |
531 | (sta->llid != llid || sta->plid != plid)) | 539 | (sta->llid != llid || sta->plid != plid)) |
532 | event = CNF_IGNR; | 540 | event = CNF_IGNR; |
533 | else | 541 | else |
534 | event = CNF_ACPT; | 542 | event = CNF_ACPT; |
@@ -555,7 +563,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
555 | default: | 563 | default: |
556 | mpl_dbg("Mesh plink: unknown frame subtype\n"); | 564 | mpl_dbg("Mesh plink: unknown frame subtype\n"); |
557 | spin_unlock_bh(&sta->plink_lock); | 565 | spin_unlock_bh(&sta->plink_lock); |
558 | sta_info_put(sta); | 566 | rcu_read_unlock(); |
559 | return; | 567 | return; |
560 | } | 568 | } |
561 | } | 569 | } |
@@ -659,8 +667,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
659 | plid, 0); | 667 | plid, 0); |
660 | break; | 668 | break; |
661 | case CNF_ACPT: | 669 | case CNF_ACPT: |
662 | if (del_timer(&sta->plink_timer)) | 670 | del_timer(&sta->plink_timer); |
663 | sta_info_put(sta); | ||
664 | sta->plink_state = ESTAB; | 671 | sta->plink_state = ESTAB; |
665 | mesh_plink_inc_estab_count(sdata); | 672 | mesh_plink_inc_estab_count(sdata); |
666 | spin_unlock_bh(&sta->plink_lock); | 673 | spin_unlock_bh(&sta->plink_lock); |
@@ -693,8 +700,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
693 | plid, reason); | 700 | plid, reason); |
694 | break; | 701 | break; |
695 | case OPN_ACPT: | 702 | case OPN_ACPT: |
696 | if (del_timer(&sta->plink_timer)) | 703 | del_timer(&sta->plink_timer); |
697 | sta_info_put(sta); | ||
698 | sta->plink_state = ESTAB; | 704 | sta->plink_state = ESTAB; |
699 | mesh_plink_inc_estab_count(sdata); | 705 | mesh_plink_inc_estab_count(sdata); |
700 | spin_unlock_bh(&sta->plink_lock); | 706 | spin_unlock_bh(&sta->plink_lock); |
@@ -717,9 +723,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
717 | __mesh_plink_deactivate(sta); | 723 | __mesh_plink_deactivate(sta); |
718 | sta->plink_state = HOLDING; | 724 | sta->plink_state = HOLDING; |
719 | llid = sta->llid; | 725 | llid = sta->llid; |
720 | if (!mod_plink_timer(sta, | 726 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
721 | dot11MeshHoldingTimeout(sdata))) | ||
722 | __sta_info_get(sta); | ||
723 | spin_unlock_bh(&sta->plink_lock); | 727 | spin_unlock_bh(&sta->plink_lock); |
724 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 728 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, |
725 | plid, reason); | 729 | plid, reason); |
@@ -738,10 +742,8 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
738 | case HOLDING: | 742 | case HOLDING: |
739 | switch (event) { | 743 | switch (event) { |
740 | case CLS_ACPT: | 744 | case CLS_ACPT: |
741 | if (del_timer(&sta->plink_timer)) { | 745 | if (del_timer(&sta->plink_timer)) |
742 | sta->ignore_plink_timer = 1; | 746 | sta->ignore_plink_timer = 1; |
743 | sta_info_put(sta); | ||
744 | } | ||
745 | mesh_plink_fsm_restart(sta); | 747 | mesh_plink_fsm_restart(sta); |
746 | spin_unlock_bh(&sta->plink_lock); | 748 | spin_unlock_bh(&sta->plink_lock); |
747 | break; | 749 | break; |
@@ -766,5 +768,6 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
766 | spin_unlock_bh(&sta->plink_lock); | 768 | spin_unlock_bh(&sta->plink_lock); |
767 | break; | 769 | break; |
768 | } | 770 | } |
769 | sta_info_put(sta); | 771 | |
772 | rcu_read_unlock(); | ||
770 | } | 773 | } |