diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 64 |
1 files changed, 13 insertions, 51 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index eeb16926aa7d..f2aefd4b8637 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -27,6 +27,9 @@ void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata) | |||
27 | skb_queue_head_init(&sdata->fragments[i].skb_list); | 27 | skb_queue_head_init(&sdata->fragments[i].skb_list); |
28 | 28 | ||
29 | INIT_LIST_HEAD(&sdata->key_list); | 29 | INIT_LIST_HEAD(&sdata->key_list); |
30 | |||
31 | sdata->force_unicast_rateidx = -1; | ||
32 | sdata->max_ratectrl_rateidx = -1; | ||
30 | } | 33 | } |
31 | 34 | ||
32 | static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata) | 35 | static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata) |
@@ -38,12 +41,11 @@ static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata) | |||
38 | } | 41 | } |
39 | 42 | ||
40 | /* Must be called with rtnl lock held. */ | 43 | /* Must be called with rtnl lock held. */ |
41 | int ieee80211_if_add(struct net_device *dev, const char *name, | 44 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
42 | struct net_device **new_dev, int type, | 45 | struct net_device **new_dev, int type, |
43 | struct vif_params *params) | 46 | struct vif_params *params) |
44 | { | 47 | { |
45 | struct net_device *ndev; | 48 | struct net_device *ndev; |
46 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
47 | struct ieee80211_sub_if_data *sdata = NULL; | 49 | struct ieee80211_sub_if_data *sdata = NULL; |
48 | int ret; | 50 | int ret; |
49 | 51 | ||
@@ -67,13 +69,10 @@ int ieee80211_if_add(struct net_device *dev, const char *name, | |||
67 | goto fail; | 69 | goto fail; |
68 | 70 | ||
69 | memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | 71 | memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); |
70 | ndev->base_addr = dev->base_addr; | ||
71 | ndev->irq = dev->irq; | ||
72 | ndev->mem_start = dev->mem_start; | ||
73 | ndev->mem_end = dev->mem_end; | ||
74 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); | 72 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); |
75 | 73 | ||
76 | sdata = IEEE80211_DEV_TO_SUB_IF(ndev); | 74 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ |
75 | sdata = netdev_priv(ndev); | ||
77 | ndev->ieee80211_ptr = &sdata->wdev; | 76 | ndev->ieee80211_ptr = &sdata->wdev; |
78 | sdata->wdev.wiphy = local->hw.wiphy; | 77 | sdata->wdev.wiphy = local->hw.wiphy; |
79 | sdata->vif.type = IEEE80211_IF_TYPE_AP; | 78 | sdata->vif.type = IEEE80211_IF_TYPE_AP; |
@@ -117,14 +116,6 @@ void ieee80211_if_set_type(struct net_device *dev, int type) | |||
117 | int oldtype = sdata->vif.type; | 116 | int oldtype = sdata->vif.type; |
118 | 117 | ||
119 | /* | 118 | /* |
120 | * We need to call this function on the master interface | ||
121 | * which already has a hard_start_xmit routine assigned | ||
122 | * which must not be changed. | ||
123 | */ | ||
124 | if (dev != sdata->local->mdev) | ||
125 | dev->hard_start_xmit = ieee80211_subif_start_xmit; | ||
126 | |||
127 | /* | ||
128 | * Called even when register_netdevice fails, it would | 119 | * Called even when register_netdevice fails, it would |
129 | * oops if assigned before initialising the rest. | 120 | * oops if assigned before initialising the rest. |
130 | */ | 121 | */ |
@@ -138,22 +129,16 @@ void ieee80211_if_set_type(struct net_device *dev, int type) | |||
138 | 129 | ||
139 | switch (type) { | 130 | switch (type) { |
140 | case IEEE80211_IF_TYPE_WDS: | 131 | case IEEE80211_IF_TYPE_WDS: |
141 | /* nothing special */ | ||
142 | break; | ||
143 | case IEEE80211_IF_TYPE_VLAN: | 132 | case IEEE80211_IF_TYPE_VLAN: |
144 | sdata->u.vlan.ap = NULL; | 133 | /* nothing special */ |
145 | break; | 134 | break; |
146 | case IEEE80211_IF_TYPE_AP: | 135 | case IEEE80211_IF_TYPE_AP: |
147 | sdata->u.ap.force_unicast_rateidx = -1; | ||
148 | sdata->u.ap.max_ratectrl_rateidx = -1; | ||
149 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); | 136 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); |
150 | sdata->bss = &sdata->u.ap; | ||
151 | INIT_LIST_HEAD(&sdata->u.ap.vlans); | 137 | INIT_LIST_HEAD(&sdata->u.ap.vlans); |
152 | break; | 138 | break; |
153 | case IEEE80211_IF_TYPE_MESH_POINT: | 139 | case IEEE80211_IF_TYPE_MESH_POINT: |
154 | case IEEE80211_IF_TYPE_STA: | 140 | case IEEE80211_IF_TYPE_STA: |
155 | case IEEE80211_IF_TYPE_IBSS: { | 141 | case IEEE80211_IF_TYPE_IBSS: { |
156 | struct ieee80211_sub_if_data *msdata; | ||
157 | struct ieee80211_if_sta *ifsta; | 142 | struct ieee80211_if_sta *ifsta; |
158 | 143 | ||
159 | ifsta = &sdata->u.sta; | 144 | ifsta = &sdata->u.sta; |
@@ -171,9 +156,6 @@ void ieee80211_if_set_type(struct net_device *dev, int type) | |||
171 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) | 156 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) |
172 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; | 157 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; |
173 | 158 | ||
174 | msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev); | ||
175 | sdata->bss = &msdata->u.ap; | ||
176 | |||
177 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 159 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
178 | ieee80211_mesh_init_sdata(sdata); | 160 | ieee80211_mesh_init_sdata(sdata); |
179 | break; | 161 | break; |
@@ -215,27 +197,8 @@ void ieee80211_if_reinit(struct net_device *dev) | |||
215 | WARN_ON(1); | 197 | WARN_ON(1); |
216 | break; | 198 | break; |
217 | case IEEE80211_IF_TYPE_AP: { | 199 | case IEEE80211_IF_TYPE_AP: { |
218 | /* Remove all virtual interfaces that use this BSS | ||
219 | * as their sdata->bss */ | ||
220 | struct ieee80211_sub_if_data *tsdata, *n; | ||
221 | struct beacon_data *beacon; | 200 | struct beacon_data *beacon; |
222 | 201 | ||
223 | list_for_each_entry_safe(tsdata, n, &local->interfaces, list) { | ||
224 | if (tsdata != sdata && tsdata->bss == &sdata->u.ap) { | ||
225 | printk(KERN_DEBUG "%s: removing virtual " | ||
226 | "interface %s because its BSS interface" | ||
227 | " is being removed\n", | ||
228 | sdata->dev->name, tsdata->dev->name); | ||
229 | list_del_rcu(&tsdata->list); | ||
230 | /* | ||
231 | * We have lots of time and can afford | ||
232 | * to sync for each interface | ||
233 | */ | ||
234 | synchronize_rcu(); | ||
235 | __ieee80211_if_del(local, tsdata); | ||
236 | } | ||
237 | } | ||
238 | |||
239 | beacon = sdata->u.ap.beacon; | 202 | beacon = sdata->u.ap.beacon; |
240 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); | 203 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); |
241 | synchronize_rcu(); | 204 | synchronize_rcu(); |
@@ -249,6 +212,7 @@ void ieee80211_if_reinit(struct net_device *dev) | |||
249 | break; | 212 | break; |
250 | } | 213 | } |
251 | case IEEE80211_IF_TYPE_WDS: | 214 | case IEEE80211_IF_TYPE_WDS: |
215 | case IEEE80211_IF_TYPE_VLAN: | ||
252 | /* nothing to do */ | 216 | /* nothing to do */ |
253 | break; | 217 | break; |
254 | case IEEE80211_IF_TYPE_MESH_POINT: | 218 | case IEEE80211_IF_TYPE_MESH_POINT: |
@@ -269,9 +233,6 @@ void ieee80211_if_reinit(struct net_device *dev) | |||
269 | case IEEE80211_IF_TYPE_MNTR: | 233 | case IEEE80211_IF_TYPE_MNTR: |
270 | dev->type = ARPHRD_ETHER; | 234 | dev->type = ARPHRD_ETHER; |
271 | break; | 235 | break; |
272 | case IEEE80211_IF_TYPE_VLAN: | ||
273 | sdata->u.vlan.ap = NULL; | ||
274 | break; | ||
275 | } | 236 | } |
276 | 237 | ||
277 | flushed = sta_info_flush(local, sdata); | 238 | flushed = sta_info_flush(local, sdata); |
@@ -289,8 +250,10 @@ void __ieee80211_if_del(struct ieee80211_local *local, | |||
289 | 250 | ||
290 | ieee80211_debugfs_remove_netdev(sdata); | 251 | ieee80211_debugfs_remove_netdev(sdata); |
291 | unregister_netdevice(dev); | 252 | unregister_netdevice(dev); |
292 | /* Except master interface, the net_device will be freed by | 253 | /* |
293 | * net_device->destructor (i. e. ieee80211_if_free). */ | 254 | * The net_device will be freed by its destructor, |
255 | * i.e. ieee80211_if_free. | ||
256 | */ | ||
294 | } | 257 | } |
295 | 258 | ||
296 | /* Must be called with rtnl lock held. */ | 259 | /* Must be called with rtnl lock held. */ |
@@ -303,8 +266,7 @@ int ieee80211_if_remove(struct net_device *dev, const char *name, int id) | |||
303 | 266 | ||
304 | list_for_each_entry_safe(sdata, n, &local->interfaces, list) { | 267 | list_for_each_entry_safe(sdata, n, &local->interfaces, list) { |
305 | if ((sdata->vif.type == id || id == -1) && | 268 | if ((sdata->vif.type == id || id == -1) && |
306 | strcmp(name, sdata->dev->name) == 0 && | 269 | strcmp(name, sdata->dev->name) == 0) { |
307 | sdata->dev != local->mdev) { | ||
308 | list_del_rcu(&sdata->list); | 270 | list_del_rcu(&sdata->list); |
309 | synchronize_rcu(); | 271 | synchronize_rcu(); |
310 | __ieee80211_if_del(local, sdata); | 272 | __ieee80211_if_del(local, sdata); |