diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 102 |
1 files changed, 82 insertions, 20 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 32abae3ce32a..edf21cebeee8 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 | ||
@@ -779,7 +793,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
779 | * and goes into the requested mode. | 793 | * and goes into the requested mode. |
780 | */ | 794 | */ |
781 | 795 | ||
782 | if (netif_running(sdata->dev)) | 796 | if (ieee80211_sdata_running(sdata)) |
783 | return -EBUSY; | 797 | return -EBUSY; |
784 | 798 | ||
785 | /* Purge and reset type-dependent state. */ | 799 | /* Purge and reset type-dependent state. */ |
@@ -833,6 +847,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
833 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ | 847 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ |
834 | sdata = netdev_priv(ndev); | 848 | sdata = netdev_priv(ndev); |
835 | ndev->ieee80211_ptr = &sdata->wdev; | 849 | ndev->ieee80211_ptr = &sdata->wdev; |
850 | memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); | ||
851 | memcpy(sdata->name, ndev->name, IFNAMSIZ); | ||
836 | 852 | ||
837 | /* initialise type-independent data */ | 853 | /* initialise type-independent data */ |
838 | sdata->wdev.wiphy = local->hw.wiphy; | 854 | sdata->wdev.wiphy = local->hw.wiphy; |
@@ -844,8 +860,12 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
844 | 860 | ||
845 | INIT_LIST_HEAD(&sdata->key_list); | 861 | INIT_LIST_HEAD(&sdata->key_list); |
846 | 862 | ||
847 | sdata->force_unicast_rateidx = -1; | 863 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
848 | sdata->max_ratectrl_rateidx = -1; | 864 | struct ieee80211_supported_band *sband; |
865 | sband = local->hw.wiphy->bands[i]; | ||
866 | sdata->rc_rateidx_mask[i] = | ||
867 | sband ? (1 << sband->n_bitrates) - 1 : 0; | ||
868 | } | ||
849 | 869 | ||
850 | /* setup type-dependent data */ | 870 | /* setup type-dependent data */ |
851 | ieee80211_setup_sdata(sdata, type); | 871 | ieee80211_setup_sdata(sdata, type); |
@@ -938,6 +958,8 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local) | |||
938 | wiphy_name(local->hw.wiphy)); | 958 | wiphy_name(local->hw.wiphy)); |
939 | #endif | 959 | #endif |
940 | 960 | ||
961 | drv_flush(local, false); | ||
962 | |||
941 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; | 963 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; |
942 | return IEEE80211_CONF_CHANGE_IDLE; | 964 | return IEEE80211_CONF_CHANGE_IDLE; |
943 | } | 965 | } |
@@ -947,16 +969,18 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
947 | struct ieee80211_sub_if_data *sdata; | 969 | struct ieee80211_sub_if_data *sdata; |
948 | int count = 0; | 970 | int count = 0; |
949 | 971 | ||
972 | if (!list_empty(&local->work_list)) | ||
973 | return ieee80211_idle_off(local, "working"); | ||
974 | |||
950 | if (local->scanning) | 975 | if (local->scanning) |
951 | return ieee80211_idle_off(local, "scanning"); | 976 | return ieee80211_idle_off(local, "scanning"); |
952 | 977 | ||
953 | list_for_each_entry(sdata, &local->interfaces, list) { | 978 | list_for_each_entry(sdata, &local->interfaces, list) { |
954 | if (!netif_running(sdata->dev)) | 979 | if (!ieee80211_sdata_running(sdata)) |
955 | continue; | 980 | continue; |
956 | /* do not count disabled managed interfaces */ | 981 | /* do not count disabled managed interfaces */ |
957 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 982 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
958 | !sdata->u.mgd.associated && | 983 | !sdata->u.mgd.associated) |
959 | list_empty(&sdata->u.mgd.work_list)) | ||
960 | continue; | 984 | continue; |
961 | /* do not count unused IBSS interfaces */ | 985 | /* do not count unused IBSS interfaces */ |
962 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | 986 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
@@ -984,3 +1008,41 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) | |||
984 | if (chg) | 1008 | if (chg) |
985 | ieee80211_hw_config(local, chg); | 1009 | ieee80211_hw_config(local, chg); |
986 | } | 1010 | } |
1011 | |||
1012 | static int netdev_notify(struct notifier_block *nb, | ||
1013 | unsigned long state, | ||
1014 | void *ndev) | ||
1015 | { | ||
1016 | struct net_device *dev = ndev; | ||
1017 | struct ieee80211_sub_if_data *sdata; | ||
1018 | |||
1019 | if (state != NETDEV_CHANGENAME) | ||
1020 | return 0; | ||
1021 | |||
1022 | if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) | ||
1023 | return 0; | ||
1024 | |||
1025 | if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) | ||
1026 | return 0; | ||
1027 | |||
1028 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1029 | |||
1030 | memcpy(sdata->name, sdata->name, IFNAMSIZ); | ||
1031 | |||
1032 | ieee80211_debugfs_rename_netdev(sdata); | ||
1033 | return 0; | ||
1034 | } | ||
1035 | |||
1036 | static struct notifier_block mac80211_netdev_notifier = { | ||
1037 | .notifier_call = netdev_notify, | ||
1038 | }; | ||
1039 | |||
1040 | int ieee80211_iface_init(void) | ||
1041 | { | ||
1042 | return register_netdevice_notifier(&mac80211_netdev_notifier); | ||
1043 | } | ||
1044 | |||
1045 | void ieee80211_iface_exit(void) | ||
1046 | { | ||
1047 | unregister_netdevice_notifier(&mac80211_netdev_notifier); | ||
1048 | } | ||