diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 94 |
1 files changed, 76 insertions, 18 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ff762ed34f1e..264a6c975f8b 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -62,6 +62,23 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | |||
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | 64 | ||
65 | static int ieee80211_change_mac(struct net_device *dev, void *addr) | ||
66 | { | ||
67 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
68 | struct sockaddr *sa = addr; | ||
69 | int ret; | ||
70 | |||
71 | if (ieee80211_sdata_running(sdata)) | ||
72 | return -EBUSY; | ||
73 | |||
74 | ret = eth_mac_addr(dev, sa); | ||
75 | |||
76 | if (ret == 0) | ||
77 | memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN); | ||
78 | |||
79 | return ret; | ||
80 | } | ||
81 | |||
65 | static inline int identical_mac_addr_allowed(int type1, int type2) | 82 | static inline int identical_mac_addr_allowed(int type1, int type2) |
66 | { | 83 | { |
67 | return type1 == NL80211_IFTYPE_MONITOR || | 84 | return type1 == NL80211_IFTYPE_MONITOR || |
@@ -82,7 +99,6 @@ static int ieee80211_open(struct net_device *dev) | |||
82 | struct ieee80211_sub_if_data *nsdata; | 99 | struct ieee80211_sub_if_data *nsdata; |
83 | struct ieee80211_local *local = sdata->local; | 100 | struct ieee80211_local *local = sdata->local; |
84 | struct sta_info *sta; | 101 | struct sta_info *sta; |
85 | struct ieee80211_if_init_conf conf; | ||
86 | u32 changed = 0; | 102 | u32 changed = 0; |
87 | int res; | 103 | int res; |
88 | u32 hw_reconf_flags = 0; | 104 | u32 hw_reconf_flags = 0; |
@@ -97,7 +113,7 @@ static int ieee80211_open(struct net_device *dev) | |||
97 | list_for_each_entry(nsdata, &local->interfaces, list) { | 113 | list_for_each_entry(nsdata, &local->interfaces, list) { |
98 | struct net_device *ndev = nsdata->dev; | 114 | struct net_device *ndev = nsdata->dev; |
99 | 115 | ||
100 | if (ndev != dev && netif_running(ndev)) { | 116 | if (ndev != dev && ieee80211_sdata_running(nsdata)) { |
101 | /* | 117 | /* |
102 | * Allow only a single IBSS interface to be up at any | 118 | * Allow only a single IBSS interface to be up at any |
103 | * time. This is restricted because beacon distribution | 119 | * time. This is restricted because beacon distribution |
@@ -183,7 +199,7 @@ static int ieee80211_open(struct net_device *dev) | |||
183 | struct net_device *ndev = nsdata->dev; | 199 | struct net_device *ndev = nsdata->dev; |
184 | 200 | ||
185 | /* | 201 | /* |
186 | * No need to check netif_running since we do not allow | 202 | * No need to check running since we do not allow |
187 | * it to start up with this invalid address. | 203 | * it to start up with this invalid address. |
188 | */ | 204 | */ |
189 | if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) { | 205 | if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) { |
@@ -234,10 +250,7 @@ static int ieee80211_open(struct net_device *dev) | |||
234 | ieee80211_configure_filter(local); | 250 | ieee80211_configure_filter(local); |
235 | break; | 251 | break; |
236 | default: | 252 | default: |
237 | conf.vif = &sdata->vif; | 253 | res = drv_add_interface(local, &sdata->vif); |
238 | conf.type = sdata->vif.type; | ||
239 | conf.mac_addr = dev->dev_addr; | ||
240 | res = drv_add_interface(local, &conf); | ||
241 | if (res) | 254 | if (res) |
242 | goto err_stop; | 255 | goto err_stop; |
243 | 256 | ||
@@ -320,7 +333,7 @@ static int ieee80211_open(struct net_device *dev) | |||
320 | 333 | ||
321 | return 0; | 334 | return 0; |
322 | err_del_interface: | 335 | err_del_interface: |
323 | drv_remove_interface(local, &conf); | 336 | drv_remove_interface(local, &sdata->vif); |
324 | err_stop: | 337 | err_stop: |
325 | if (!local->open_count) | 338 | if (!local->open_count) |
326 | drv_stop(local); | 339 | drv_stop(local); |
@@ -335,7 +348,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
335 | { | 348 | { |
336 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 349 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
337 | struct ieee80211_local *local = sdata->local; | 350 | struct ieee80211_local *local = sdata->local; |
338 | struct ieee80211_if_init_conf conf; | ||
339 | struct sta_info *sta; | 351 | struct sta_info *sta; |
340 | unsigned long flags; | 352 | unsigned long flags; |
341 | struct sk_buff *skb, *tmp; | 353 | struct sk_buff *skb, *tmp; |
@@ -348,6 +360,11 @@ static int ieee80211_stop(struct net_device *dev) | |||
348 | netif_tx_stop_all_queues(dev); | 360 | netif_tx_stop_all_queues(dev); |
349 | 361 | ||
350 | /* | 362 | /* |
363 | * Purge work for this interface. | ||
364 | */ | ||
365 | ieee80211_work_purge(sdata); | ||
366 | |||
367 | /* | ||
351 | * Now delete all active aggregation sessions. | 368 | * Now delete all active aggregation sessions. |
352 | */ | 369 | */ |
353 | rcu_read_lock(); | 370 | rcu_read_lock(); |
@@ -514,12 +531,9 @@ static int ieee80211_stop(struct net_device *dev) | |||
514 | BSS_CHANGED_BEACON_ENABLED); | 531 | BSS_CHANGED_BEACON_ENABLED); |
515 | } | 532 | } |
516 | 533 | ||
517 | conf.vif = &sdata->vif; | ||
518 | conf.type = sdata->vif.type; | ||
519 | conf.mac_addr = dev->dev_addr; | ||
520 | /* disable all keys for as long as this netdev is down */ | 534 | /* disable all keys for as long as this netdev is down */ |
521 | ieee80211_disable_keys(sdata); | 535 | ieee80211_disable_keys(sdata); |
522 | drv_remove_interface(local, &conf); | 536 | drv_remove_interface(local, &sdata->vif); |
523 | } | 537 | } |
524 | 538 | ||
525 | sdata->bss = NULL; | 539 | sdata->bss = NULL; |
@@ -659,7 +673,7 @@ static const struct net_device_ops ieee80211_dataif_ops = { | |||
659 | .ndo_start_xmit = ieee80211_subif_start_xmit, | 673 | .ndo_start_xmit = ieee80211_subif_start_xmit, |
660 | .ndo_set_multicast_list = ieee80211_set_multicast_list, | 674 | .ndo_set_multicast_list = ieee80211_set_multicast_list, |
661 | .ndo_change_mtu = ieee80211_change_mtu, | 675 | .ndo_change_mtu = ieee80211_change_mtu, |
662 | .ndo_set_mac_address = eth_mac_addr, | 676 | .ndo_set_mac_address = ieee80211_change_mac, |
663 | .ndo_select_queue = ieee80211_netdev_select_queue, | 677 | .ndo_select_queue = ieee80211_netdev_select_queue, |
664 | }; | 678 | }; |
665 | 679 | ||
@@ -775,7 +789,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
775 | * and goes into the requested mode. | 789 | * and goes into the requested mode. |
776 | */ | 790 | */ |
777 | 791 | ||
778 | if (netif_running(sdata->dev)) | 792 | if (ieee80211_sdata_running(sdata)) |
779 | return -EBUSY; | 793 | return -EBUSY; |
780 | 794 | ||
781 | /* Purge and reset type-dependent state. */ | 795 | /* Purge and reset type-dependent state. */ |
@@ -829,6 +843,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
829 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ | 843 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ |
830 | sdata = netdev_priv(ndev); | 844 | sdata = netdev_priv(ndev); |
831 | ndev->ieee80211_ptr = &sdata->wdev; | 845 | ndev->ieee80211_ptr = &sdata->wdev; |
846 | memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); | ||
847 | memcpy(sdata->name, ndev->name, IFNAMSIZ); | ||
832 | 848 | ||
833 | /* initialise type-independent data */ | 849 | /* initialise type-independent data */ |
834 | sdata->wdev.wiphy = local->hw.wiphy; | 850 | sdata->wdev.wiphy = local->hw.wiphy; |
@@ -934,6 +950,8 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local) | |||
934 | wiphy_name(local->hw.wiphy)); | 950 | wiphy_name(local->hw.wiphy)); |
935 | #endif | 951 | #endif |
936 | 952 | ||
953 | drv_flush(local, false); | ||
954 | |||
937 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; | 955 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; |
938 | return IEEE80211_CONF_CHANGE_IDLE; | 956 | return IEEE80211_CONF_CHANGE_IDLE; |
939 | } | 957 | } |
@@ -943,16 +961,18 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
943 | struct ieee80211_sub_if_data *sdata; | 961 | struct ieee80211_sub_if_data *sdata; |
944 | int count = 0; | 962 | int count = 0; |
945 | 963 | ||
964 | if (!list_empty(&local->work_list)) | ||
965 | return ieee80211_idle_off(local, "working"); | ||
966 | |||
946 | if (local->scanning) | 967 | if (local->scanning) |
947 | return ieee80211_idle_off(local, "scanning"); | 968 | return ieee80211_idle_off(local, "scanning"); |
948 | 969 | ||
949 | list_for_each_entry(sdata, &local->interfaces, list) { | 970 | list_for_each_entry(sdata, &local->interfaces, list) { |
950 | if (!netif_running(sdata->dev)) | 971 | if (!ieee80211_sdata_running(sdata)) |
951 | continue; | 972 | continue; |
952 | /* do not count disabled managed interfaces */ | 973 | /* do not count disabled managed interfaces */ |
953 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 974 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
954 | !sdata->u.mgd.associated && | 975 | !sdata->u.mgd.associated) |
955 | list_empty(&sdata->u.mgd.work_list)) | ||
956 | continue; | 976 | continue; |
957 | /* do not count unused IBSS interfaces */ | 977 | /* do not count unused IBSS interfaces */ |
958 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | 978 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
@@ -980,3 +1000,41 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) | |||
980 | if (chg) | 1000 | if (chg) |
981 | ieee80211_hw_config(local, chg); | 1001 | ieee80211_hw_config(local, chg); |
982 | } | 1002 | } |
1003 | |||
1004 | static int netdev_notify(struct notifier_block *nb, | ||
1005 | unsigned long state, | ||
1006 | void *ndev) | ||
1007 | { | ||
1008 | struct net_device *dev = ndev; | ||
1009 | struct ieee80211_sub_if_data *sdata; | ||
1010 | |||
1011 | if (state != NETDEV_CHANGENAME) | ||
1012 | return 0; | ||
1013 | |||
1014 | if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) | ||
1015 | return 0; | ||
1016 | |||
1017 | if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) | ||
1018 | return 0; | ||
1019 | |||
1020 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1021 | |||
1022 | memcpy(sdata->name, sdata->name, IFNAMSIZ); | ||
1023 | |||
1024 | ieee80211_debugfs_rename_netdev(sdata); | ||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | static struct notifier_block mac80211_netdev_notifier = { | ||
1029 | .notifier_call = netdev_notify, | ||
1030 | }; | ||
1031 | |||
1032 | int ieee80211_iface_init(void) | ||
1033 | { | ||
1034 | return register_netdevice_notifier(&mac80211_netdev_notifier); | ||
1035 | } | ||
1036 | |||
1037 | void ieee80211_iface_exit(void) | ||
1038 | { | ||
1039 | unregister_netdevice_notifier(&mac80211_netdev_notifier); | ||
1040 | } | ||