aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c64
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
32static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata) 35static 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. */
41int ieee80211_if_add(struct net_device *dev, const char *name, 44int 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);