diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index de7ddc303a5f..14212ad41e5a 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -701,6 +701,67 @@ static void ieee80211_if_setup(struct net_device *dev) | |||
701 | dev->destructor = free_netdev; | 701 | dev->destructor = free_netdev; |
702 | } | 702 | } |
703 | 703 | ||
704 | static void ieee80211_iface_work(struct work_struct *work) | ||
705 | { | ||
706 | struct ieee80211_sub_if_data *sdata = | ||
707 | container_of(work, struct ieee80211_sub_if_data, work); | ||
708 | struct ieee80211_local *local = sdata->local; | ||
709 | struct sk_buff *skb; | ||
710 | |||
711 | if (!ieee80211_sdata_running(sdata)) | ||
712 | return; | ||
713 | |||
714 | if (local->scanning) | ||
715 | return; | ||
716 | |||
717 | /* | ||
718 | * ieee80211_queue_work() should have picked up most cases, | ||
719 | * here we'll pick the rest. | ||
720 | */ | ||
721 | if (WARN(local->suspended, | ||
722 | "interface work scheduled while going to suspend\n")) | ||
723 | return; | ||
724 | |||
725 | /* first process frames */ | ||
726 | while ((skb = skb_dequeue(&sdata->skb_queue))) { | ||
727 | switch (sdata->vif.type) { | ||
728 | case NL80211_IFTYPE_STATION: | ||
729 | ieee80211_sta_rx_queued_mgmt(sdata, skb); | ||
730 | break; | ||
731 | case NL80211_IFTYPE_ADHOC: | ||
732 | ieee80211_ibss_rx_queued_mgmt(sdata, skb); | ||
733 | break; | ||
734 | case NL80211_IFTYPE_MESH_POINT: | ||
735 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | ||
736 | break; | ||
737 | ieee80211_mesh_rx_queued_mgmt(sdata, skb); | ||
738 | break; | ||
739 | default: | ||
740 | WARN(1, "frame for unexpected interface type"); | ||
741 | kfree_skb(skb); | ||
742 | break; | ||
743 | } | ||
744 | } | ||
745 | |||
746 | /* then other type-dependent work */ | ||
747 | switch (sdata->vif.type) { | ||
748 | case NL80211_IFTYPE_STATION: | ||
749 | ieee80211_sta_work(sdata); | ||
750 | break; | ||
751 | case NL80211_IFTYPE_ADHOC: | ||
752 | ieee80211_ibss_work(sdata); | ||
753 | break; | ||
754 | case NL80211_IFTYPE_MESH_POINT: | ||
755 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | ||
756 | break; | ||
757 | ieee80211_mesh_work(sdata); | ||
758 | break; | ||
759 | default: | ||
760 | break; | ||
761 | } | ||
762 | } | ||
763 | |||
764 | |||
704 | /* | 765 | /* |
705 | * Helper function to initialise an interface to a specific type. | 766 | * Helper function to initialise an interface to a specific type. |
706 | */ | 767 | */ |
@@ -719,6 +780,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
719 | sdata->dev->type = ARPHRD_ETHER; | 780 | sdata->dev->type = ARPHRD_ETHER; |
720 | 781 | ||
721 | skb_queue_head_init(&sdata->skb_queue); | 782 | skb_queue_head_init(&sdata->skb_queue); |
783 | INIT_WORK(&sdata->work, ieee80211_iface_work); | ||
722 | 784 | ||
723 | switch (type) { | 785 | switch (type) { |
724 | case NL80211_IFTYPE_AP: | 786 | case NL80211_IFTYPE_AP: |