diff options
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 166 |
1 files changed, 40 insertions, 126 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 092a017b237e..0c4f8e122ed6 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -77,81 +77,23 @@ void ieee80211_configure_filter(struct ieee80211_local *local) | |||
77 | if (local->fif_other_bss) | 77 | if (local->fif_other_bss) |
78 | new_flags |= FIF_OTHER_BSS; | 78 | new_flags |= FIF_OTHER_BSS; |
79 | 79 | ||
80 | if (local->fif_pspoll) | ||
81 | new_flags |= FIF_PSPOLL; | ||
82 | |||
80 | changed_flags = local->filter_flags ^ new_flags; | 83 | changed_flags = local->filter_flags ^ new_flags; |
81 | 84 | ||
82 | /* be a bit nasty */ | 85 | /* be a bit nasty */ |
83 | new_flags |= (1<<31); | 86 | new_flags |= (1<<31); |
84 | 87 | ||
85 | drv_configure_filter(local, changed_flags, &new_flags, | 88 | drv_configure_filter(local, changed_flags, &new_flags, |
86 | local->mdev->mc_count, | 89 | local->mc_count, |
87 | local->mdev->mc_list); | 90 | local->mc_list); |
88 | 91 | ||
89 | WARN_ON(new_flags & (1<<31)); | 92 | WARN_ON(new_flags & (1<<31)); |
90 | 93 | ||
91 | local->filter_flags = new_flags & ~(1<<31); | 94 | local->filter_flags = new_flags & ~(1<<31); |
92 | } | 95 | } |
93 | 96 | ||
94 | /* master interface */ | ||
95 | |||
96 | static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr) | ||
97 | { | ||
98 | memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */ | ||
99 | return ETH_ALEN; | ||
100 | } | ||
101 | |||
102 | static const struct header_ops ieee80211_header_ops = { | ||
103 | .create = eth_header, | ||
104 | .parse = header_parse_80211, | ||
105 | .rebuild = eth_rebuild_header, | ||
106 | .cache = eth_header_cache, | ||
107 | .cache_update = eth_header_cache_update, | ||
108 | }; | ||
109 | |||
110 | static int ieee80211_master_open(struct net_device *dev) | ||
111 | { | ||
112 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
113 | struct ieee80211_local *local = mpriv->local; | ||
114 | struct ieee80211_sub_if_data *sdata; | ||
115 | int res = -EOPNOTSUPP; | ||
116 | |||
117 | /* we hold the RTNL here so can safely walk the list */ | ||
118 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
119 | if (netif_running(sdata->dev)) { | ||
120 | res = 0; | ||
121 | break; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | if (res) | ||
126 | return res; | ||
127 | |||
128 | netif_tx_start_all_queues(local->mdev); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static int ieee80211_master_stop(struct net_device *dev) | ||
134 | { | ||
135 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
136 | struct ieee80211_local *local = mpriv->local; | ||
137 | struct ieee80211_sub_if_data *sdata; | ||
138 | |||
139 | /* we hold the RTNL here so can safely walk the list */ | ||
140 | list_for_each_entry(sdata, &local->interfaces, list) | ||
141 | if (netif_running(sdata->dev)) | ||
142 | dev_close(sdata->dev); | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static void ieee80211_master_set_multicast_list(struct net_device *dev) | ||
148 | { | ||
149 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
150 | struct ieee80211_local *local = mpriv->local; | ||
151 | |||
152 | ieee80211_configure_filter(local); | ||
153 | } | ||
154 | |||
155 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | 97 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) |
156 | { | 98 | { |
157 | struct ieee80211_channel *chan, *scan_chan; | 99 | struct ieee80211_channel *chan, *scan_chan; |
@@ -259,7 +201,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
259 | } | 201 | } |
260 | 202 | ||
261 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | 203 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
262 | if (local->sw_scanning) { | 204 | if (local->quiescing || !netif_running(sdata->dev) || |
205 | test_bit(SCAN_SW_SCANNING, &local->scanning)) { | ||
263 | sdata->vif.bss_conf.enable_beacon = false; | 206 | sdata->vif.bss_conf.enable_beacon = false; |
264 | } else { | 207 | } else { |
265 | /* | 208 | /* |
@@ -310,7 +253,6 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | |||
310 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 253 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
311 | int tmp; | 254 | int tmp; |
312 | 255 | ||
313 | skb->dev = local->mdev; | ||
314 | skb->pkt_type = IEEE80211_TX_STATUS_MSG; | 256 | skb->pkt_type = IEEE80211_TX_STATUS_MSG; |
315 | skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ? | 257 | skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ? |
316 | &local->skb_queue : &local->skb_queue_unreliable, skb); | 258 | &local->skb_queue : &local->skb_queue_unreliable, skb); |
@@ -330,19 +272,16 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
330 | { | 272 | { |
331 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 273 | struct ieee80211_local *local = (struct ieee80211_local *) data; |
332 | struct sk_buff *skb; | 274 | struct sk_buff *skb; |
333 | struct ieee80211_rx_status rx_status; | ||
334 | struct ieee80211_ra_tid *ra_tid; | 275 | struct ieee80211_ra_tid *ra_tid; |
335 | 276 | ||
336 | while ((skb = skb_dequeue(&local->skb_queue)) || | 277 | while ((skb = skb_dequeue(&local->skb_queue)) || |
337 | (skb = skb_dequeue(&local->skb_queue_unreliable))) { | 278 | (skb = skb_dequeue(&local->skb_queue_unreliable))) { |
338 | switch (skb->pkt_type) { | 279 | switch (skb->pkt_type) { |
339 | case IEEE80211_RX_MSG: | 280 | case IEEE80211_RX_MSG: |
340 | /* status is in skb->cb */ | ||
341 | memcpy(&rx_status, skb->cb, sizeof(rx_status)); | ||
342 | /* Clear skb->pkt_type in order to not confuse kernel | 281 | /* Clear skb->pkt_type in order to not confuse kernel |
343 | * netstack. */ | 282 | * netstack. */ |
344 | skb->pkt_type = 0; | 283 | skb->pkt_type = 0; |
345 | __ieee80211_rx(local_to_hw(local), skb, &rx_status); | 284 | ieee80211_rx(local_to_hw(local), skb); |
346 | break; | 285 | break; |
347 | case IEEE80211_TX_STATUS_MSG: | 286 | case IEEE80211_TX_STATUS_MSG: |
348 | skb->pkt_type = 0; | 287 | skb->pkt_type = 0; |
@@ -375,6 +314,31 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
375 | { | 314 | { |
376 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 315 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
377 | 316 | ||
317 | /* | ||
318 | * XXX: This is temporary! | ||
319 | * | ||
320 | * The problem here is that when we get here, the driver will | ||
321 | * quite likely have pretty much overwritten info->control by | ||
322 | * using info->driver_data or info->rate_driver_data. Thus, | ||
323 | * when passing out the frame to the driver again, we would be | ||
324 | * passing completely bogus data since the driver would then | ||
325 | * expect a properly filled info->control. In mac80211 itself | ||
326 | * the same problem occurs, since we need info->control.vif | ||
327 | * internally. | ||
328 | * | ||
329 | * To fix this, we should send the frame through TX processing | ||
330 | * again. However, it's not that simple, since the frame will | ||
331 | * have been software-encrypted (if applicable) already, and | ||
332 | * encrypting it again doesn't do much good. So to properly do | ||
333 | * that, we not only have to skip the actual 'raw' encryption | ||
334 | * (key selection etc. still has to be done!) but also the | ||
335 | * sequence number assignment since that impacts the crypto | ||
336 | * encapsulation, of course. | ||
337 | * | ||
338 | * Hence, for now, fix the bug by just dropping the frame. | ||
339 | */ | ||
340 | goto drop; | ||
341 | |||
378 | sta->tx_filtered_count++; | 342 | sta->tx_filtered_count++; |
379 | 343 | ||
380 | /* | 344 | /* |
@@ -428,6 +392,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
428 | return; | 392 | return; |
429 | } | 393 | } |
430 | 394 | ||
395 | drop: | ||
431 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 396 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
432 | if (net_ratelimit()) | 397 | if (net_ratelimit()) |
433 | printk(KERN_DEBUG "%s: dropped TX filtered frame, " | 398 | printk(KERN_DEBUG "%s: dropped TX filtered frame, " |
@@ -685,6 +650,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
685 | if (!wiphy) | 650 | if (!wiphy) |
686 | return NULL; | 651 | return NULL; |
687 | 652 | ||
653 | wiphy->netnsok = true; | ||
688 | wiphy->privid = mac80211_wiphy_privid; | 654 | wiphy->privid = mac80211_wiphy_privid; |
689 | 655 | ||
690 | /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ | 656 | /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ |
@@ -719,7 +685,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
719 | mutex_init(&local->scan_mtx); | 685 | mutex_init(&local->scan_mtx); |
720 | 686 | ||
721 | spin_lock_init(&local->key_lock); | 687 | spin_lock_init(&local->key_lock); |
722 | 688 | spin_lock_init(&local->filter_lock); | |
723 | spin_lock_init(&local->queue_stop_reason_lock); | 689 | spin_lock_init(&local->queue_stop_reason_lock); |
724 | 690 | ||
725 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); | 691 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
@@ -755,30 +721,11 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
755 | } | 721 | } |
756 | EXPORT_SYMBOL(ieee80211_alloc_hw); | 722 | EXPORT_SYMBOL(ieee80211_alloc_hw); |
757 | 723 | ||
758 | static const struct net_device_ops ieee80211_master_ops = { | ||
759 | .ndo_start_xmit = ieee80211_master_start_xmit, | ||
760 | .ndo_open = ieee80211_master_open, | ||
761 | .ndo_stop = ieee80211_master_stop, | ||
762 | .ndo_set_multicast_list = ieee80211_master_set_multicast_list, | ||
763 | .ndo_select_queue = ieee80211_select_queue, | ||
764 | }; | ||
765 | |||
766 | static void ieee80211_master_setup(struct net_device *mdev) | ||
767 | { | ||
768 | mdev->type = ARPHRD_IEEE80211; | ||
769 | mdev->netdev_ops = &ieee80211_master_ops; | ||
770 | mdev->header_ops = &ieee80211_header_ops; | ||
771 | mdev->tx_queue_len = 1000; | ||
772 | mdev->addr_len = ETH_ALEN; | ||
773 | } | ||
774 | |||
775 | int ieee80211_register_hw(struct ieee80211_hw *hw) | 724 | int ieee80211_register_hw(struct ieee80211_hw *hw) |
776 | { | 725 | { |
777 | struct ieee80211_local *local = hw_to_local(hw); | 726 | struct ieee80211_local *local = hw_to_local(hw); |
778 | int result; | 727 | int result; |
779 | enum ieee80211_band band; | 728 | enum ieee80211_band band; |
780 | struct net_device *mdev; | ||
781 | struct ieee80211_master_priv *mpriv; | ||
782 | int channels, i, j, max_bitrates; | 729 | int channels, i, j, max_bitrates; |
783 | bool supp_ht; | 730 | bool supp_ht; |
784 | static const u32 cipher_suites[] = { | 731 | static const u32 cipher_suites[] = { |
@@ -877,19 +824,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
877 | if (hw->queues > IEEE80211_MAX_QUEUES) | 824 | if (hw->queues > IEEE80211_MAX_QUEUES) |
878 | hw->queues = IEEE80211_MAX_QUEUES; | 825 | hw->queues = IEEE80211_MAX_QUEUES; |
879 | 826 | ||
880 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), | 827 | local->workqueue = |
881 | "wmaster%d", ieee80211_master_setup, | ||
882 | hw->queues); | ||
883 | if (!mdev) | ||
884 | goto fail_mdev_alloc; | ||
885 | |||
886 | mpriv = netdev_priv(mdev); | ||
887 | mpriv->local = local; | ||
888 | local->mdev = mdev; | ||
889 | |||
890 | local->hw.workqueue = | ||
891 | create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); | 828 | create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); |
892 | if (!local->hw.workqueue) { | 829 | if (!local->workqueue) { |
893 | result = -ENOMEM; | 830 | result = -ENOMEM; |
894 | goto fail_workqueue; | 831 | goto fail_workqueue; |
895 | } | 832 | } |
@@ -921,17 +858,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
921 | } | 858 | } |
922 | 859 | ||
923 | rtnl_lock(); | 860 | rtnl_lock(); |
924 | result = dev_alloc_name(local->mdev, local->mdev->name); | ||
925 | if (result < 0) | ||
926 | goto fail_dev; | ||
927 | |||
928 | memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | ||
929 | SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy)); | ||
930 | local->mdev->features |= NETIF_F_NETNS_LOCAL; | ||
931 | |||
932 | result = register_netdevice(local->mdev); | ||
933 | if (result < 0) | ||
934 | goto fail_dev; | ||
935 | 861 | ||
936 | result = ieee80211_init_rate_ctrl_alg(local, | 862 | result = ieee80211_init_rate_ctrl_alg(local, |
937 | hw->rate_control_algorithm); | 863 | hw->rate_control_algorithm); |
@@ -984,20 +910,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
984 | ieee80211_led_exit(local); | 910 | ieee80211_led_exit(local); |
985 | ieee80211_remove_interfaces(local); | 911 | ieee80211_remove_interfaces(local); |
986 | fail_rate: | 912 | fail_rate: |
987 | unregister_netdevice(local->mdev); | ||
988 | local->mdev = NULL; | ||
989 | fail_dev: | ||
990 | rtnl_unlock(); | 913 | rtnl_unlock(); |
991 | ieee80211_wep_free(local); | 914 | ieee80211_wep_free(local); |
992 | fail_wep: | 915 | fail_wep: |
993 | sta_info_stop(local); | 916 | sta_info_stop(local); |
994 | fail_sta_info: | 917 | fail_sta_info: |
995 | debugfs_hw_del(local); | 918 | debugfs_hw_del(local); |
996 | destroy_workqueue(local->hw.workqueue); | 919 | destroy_workqueue(local->workqueue); |
997 | fail_workqueue: | 920 | fail_workqueue: |
998 | if (local->mdev) | ||
999 | free_netdev(local->mdev); | ||
1000 | fail_mdev_alloc: | ||
1001 | wiphy_unregister(local->hw.wiphy); | 921 | wiphy_unregister(local->hw.wiphy); |
1002 | fail_wiphy_register: | 922 | fail_wiphy_register: |
1003 | kfree(local->int_scan_req.channels); | 923 | kfree(local->int_scan_req.channels); |
@@ -1022,13 +942,8 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1022 | * because the driver cannot be handing us frames any | 942 | * because the driver cannot be handing us frames any |
1023 | * more and the tasklet is killed. | 943 | * more and the tasklet is killed. |
1024 | */ | 944 | */ |
1025 | |||
1026 | /* First, we remove all virtual interfaces. */ | ||
1027 | ieee80211_remove_interfaces(local); | 945 | ieee80211_remove_interfaces(local); |
1028 | 946 | ||
1029 | /* then, finally, remove the master interface */ | ||
1030 | unregister_netdevice(local->mdev); | ||
1031 | |||
1032 | rtnl_unlock(); | 947 | rtnl_unlock(); |
1033 | 948 | ||
1034 | ieee80211_clear_tx_pending(local); | 949 | ieee80211_clear_tx_pending(local); |
@@ -1043,11 +958,10 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1043 | skb_queue_purge(&local->skb_queue); | 958 | skb_queue_purge(&local->skb_queue); |
1044 | skb_queue_purge(&local->skb_queue_unreliable); | 959 | skb_queue_purge(&local->skb_queue_unreliable); |
1045 | 960 | ||
1046 | destroy_workqueue(local->hw.workqueue); | 961 | destroy_workqueue(local->workqueue); |
1047 | wiphy_unregister(local->hw.wiphy); | 962 | wiphy_unregister(local->hw.wiphy); |
1048 | ieee80211_wep_free(local); | 963 | ieee80211_wep_free(local); |
1049 | ieee80211_led_exit(local); | 964 | ieee80211_led_exit(local); |
1050 | free_netdev(local->mdev); | ||
1051 | kfree(local->int_scan_req.channels); | 965 | kfree(local->int_scan_req.channels); |
1052 | } | 966 | } |
1053 | EXPORT_SYMBOL(ieee80211_unregister_hw); | 967 | EXPORT_SYMBOL(ieee80211_unregister_hw); |