aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mesh.c')
-rw-r--r--net/mac80211/mesh.c73
1 files changed, 9 insertions, 64 deletions
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index bde81031727a..c8a4f19ed13b 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -54,7 +54,7 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
54 return; 54 return;
55 } 55 }
56 56
57 ieee80211_queue_work(&local->hw, &ifmsh->work); 57 ieee80211_queue_work(&local->hw, &sdata->work);
58} 58}
59 59
60/** 60/**
@@ -345,7 +345,7 @@ static void ieee80211_mesh_path_timer(unsigned long data)
345 return; 345 return;
346 } 346 }
347 347
348 ieee80211_queue_work(&local->hw, &ifmsh->work); 348 ieee80211_queue_work(&local->hw, &sdata->work);
349} 349}
350 350
351static void ieee80211_mesh_path_root_timer(unsigned long data) 351static void ieee80211_mesh_path_root_timer(unsigned long data)
@@ -362,7 +362,7 @@ static void ieee80211_mesh_path_root_timer(unsigned long data)
362 return; 362 return;
363 } 363 }
364 364
365 ieee80211_queue_work(&local->hw, &ifmsh->work); 365 ieee80211_queue_work(&local->hw, &sdata->work);
366} 366}
367 367
368void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) 368void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
@@ -484,9 +484,6 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
484{ 484{
485 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 485 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
486 486
487 /* might restart the timer but that doesn't matter */
488 cancel_work_sync(&ifmsh->work);
489
490 /* use atomic bitops in case both timers fire at the same time */ 487 /* use atomic bitops in case both timers fire at the same time */
491 488
492 if (del_timer_sync(&ifmsh->housekeeping_timer)) 489 if (del_timer_sync(&ifmsh->housekeeping_timer))
@@ -518,7 +515,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
518 515
519 set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); 516 set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
520 ieee80211_mesh_root_setup(ifmsh); 517 ieee80211_mesh_root_setup(ifmsh);
521 ieee80211_queue_work(&local->hw, &ifmsh->work); 518 ieee80211_queue_work(&local->hw, &sdata->work);
522 sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; 519 sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
523 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | 520 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
524 BSS_CHANGED_BEACON_ENABLED | 521 BSS_CHANGED_BEACON_ENABLED |
@@ -536,16 +533,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
536 * whether the interface is running, which, at this point, 533 * whether the interface is running, which, at this point,
537 * it no longer is. 534 * it no longer is.
538 */ 535 */
539 cancel_work_sync(&sdata->u.mesh.work); 536 cancel_work_sync(&sdata->work);
540
541 /*
542 * When we get here, the interface is marked down.
543 * Call synchronize_rcu() to wait for the RX path
544 * should it be using the interface and enqueuing
545 * frames at this very time on another CPU.
546 */
547 rcu_barrier(); /* Wait for RX path and call_rcu()'s */
548 skb_queue_purge(&sdata->u.mesh.skb_queue);
549} 537}
550 538
551static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, 539static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
@@ -608,8 +596,8 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
608 } 596 }
609} 597}
610 598
611static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, 599void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
612 struct sk_buff *skb) 600 struct sk_buff *skb)
613{ 601{
614 struct ieee80211_rx_status *rx_status; 602 struct ieee80211_rx_status *rx_status;
615 struct ieee80211_if_mesh *ifmsh; 603 struct ieee80211_if_mesh *ifmsh;
@@ -632,26 +620,11 @@ static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
632 ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); 620 ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status);
633 break; 621 break;
634 } 622 }
635
636 kfree_skb(skb);
637} 623}
638 624
639static void ieee80211_mesh_work(struct work_struct *work) 625void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
640{ 626{
641 struct ieee80211_sub_if_data *sdata =
642 container_of(work, struct ieee80211_sub_if_data, u.mesh.work);
643 struct ieee80211_local *local = sdata->local;
644 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 627 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
645 struct sk_buff *skb;
646
647 if (!ieee80211_sdata_running(sdata))
648 return;
649
650 if (local->scanning)
651 return;
652
653 while ((skb = skb_dequeue(&ifmsh->skb_queue)))
654 ieee80211_mesh_rx_queued_mgmt(sdata, skb);
655 628
656 if (ifmsh->preq_queue_len && 629 if (ifmsh->preq_queue_len &&
657 time_after(jiffies, 630 time_after(jiffies,
@@ -678,7 +651,7 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
678 rcu_read_lock(); 651 rcu_read_lock();
679 list_for_each_entry_rcu(sdata, &local->interfaces, list) 652 list_for_each_entry_rcu(sdata, &local->interfaces, list)
680 if (ieee80211_vif_is_mesh(&sdata->vif)) 653 if (ieee80211_vif_is_mesh(&sdata->vif))
681 ieee80211_queue_work(&local->hw, &sdata->u.mesh.work); 654 ieee80211_queue_work(&local->hw, &sdata->work);
682 rcu_read_unlock(); 655 rcu_read_unlock();
683} 656}
684 657
@@ -686,11 +659,9 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
686{ 659{
687 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 660 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
688 661
689 INIT_WORK(&ifmsh->work, ieee80211_mesh_work);
690 setup_timer(&ifmsh->housekeeping_timer, 662 setup_timer(&ifmsh->housekeeping_timer,
691 ieee80211_mesh_housekeeping_timer, 663 ieee80211_mesh_housekeeping_timer,
692 (unsigned long) sdata); 664 (unsigned long) sdata);
693 skb_queue_head_init(&sdata->u.mesh.skb_queue);
694 665
695 ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; 666 ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T;
696 ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; 667 ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T;
@@ -731,29 +702,3 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
731 INIT_LIST_HEAD(&ifmsh->preq_queue.list); 702 INIT_LIST_HEAD(&ifmsh->preq_queue.list);
732 spin_lock_init(&ifmsh->mesh_preq_queue_lock); 703 spin_lock_init(&ifmsh->mesh_preq_queue_lock);
733} 704}
734
735ieee80211_rx_result
736ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
737{
738 struct ieee80211_local *local = sdata->local;
739 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
740 struct ieee80211_mgmt *mgmt;
741 u16 fc;
742
743 if (skb->len < 24)
744 return RX_DROP_MONITOR;
745
746 mgmt = (struct ieee80211_mgmt *) skb->data;
747 fc = le16_to_cpu(mgmt->frame_control);
748
749 switch (fc & IEEE80211_FCTL_STYPE) {
750 case IEEE80211_STYPE_ACTION:
751 case IEEE80211_STYPE_PROBE_RESP:
752 case IEEE80211_STYPE_BEACON:
753 skb_queue_tail(&ifmsh->skb_queue, skb);
754 ieee80211_queue_work(&local->hw, &ifmsh->work);
755 return RX_QUEUED;
756 }
757
758 return RX_CONTINUE;
759}