diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 30d73552e9ab..12a6d4bb5d37 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -188,11 +188,22 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
188 | if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) | 188 | if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) |
189 | return -ENOLINK; | 189 | return -ENOLINK; |
190 | break; | 190 | break; |
191 | case NL80211_IFTYPE_AP_VLAN: | 191 | case NL80211_IFTYPE_AP_VLAN: { |
192 | struct ieee80211_sub_if_data *master; | ||
193 | |||
192 | if (!sdata->bss) | 194 | if (!sdata->bss) |
193 | return -ENOLINK; | 195 | return -ENOLINK; |
196 | |||
194 | list_add(&sdata->u.vlan.list, &sdata->bss->vlans); | 197 | list_add(&sdata->u.vlan.list, &sdata->bss->vlans); |
198 | |||
199 | master = container_of(sdata->bss, | ||
200 | struct ieee80211_sub_if_data, u.ap); | ||
201 | sdata->control_port_protocol = | ||
202 | master->control_port_protocol; | ||
203 | sdata->control_port_no_encrypt = | ||
204 | master->control_port_no_encrypt; | ||
195 | break; | 205 | break; |
206 | } | ||
196 | case NL80211_IFTYPE_AP: | 207 | case NL80211_IFTYPE_AP: |
197 | sdata->bss = &sdata->u.ap; | 208 | sdata->bss = &sdata->u.ap; |
198 | break; | 209 | break; |
@@ -265,7 +276,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
265 | break; | 276 | break; |
266 | default: | 277 | default: |
267 | if (coming_up) { | 278 | if (coming_up) { |
268 | res = drv_add_interface(local, &sdata->vif); | 279 | res = drv_add_interface(local, sdata); |
269 | if (res) | 280 | if (res) |
270 | goto err_stop; | 281 | goto err_stop; |
271 | } | 282 | } |
@@ -282,10 +293,18 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
282 | changed |= ieee80211_reset_erp_info(sdata); | 293 | changed |= ieee80211_reset_erp_info(sdata); |
283 | ieee80211_bss_info_change_notify(sdata, changed); | 294 | ieee80211_bss_info_change_notify(sdata, changed); |
284 | 295 | ||
285 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 296 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
297 | sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
286 | netif_carrier_off(dev); | 298 | netif_carrier_off(dev); |
287 | else | 299 | else |
288 | netif_carrier_on(dev); | 300 | netif_carrier_on(dev); |
301 | |||
302 | /* | ||
303 | * set default queue parameters so drivers don't | ||
304 | * need to initialise the hardware if the hardware | ||
305 | * doesn't start up with sane defaults | ||
306 | */ | ||
307 | ieee80211_set_wmm_default(sdata); | ||
289 | } | 308 | } |
290 | 309 | ||
291 | set_bit(SDATA_STATE_RUNNING, &sdata->state); | 310 | set_bit(SDATA_STATE_RUNNING, &sdata->state); |
@@ -329,15 +348,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
329 | if (coming_up) | 348 | if (coming_up) |
330 | local->open_count++; | 349 | local->open_count++; |
331 | 350 | ||
332 | if (hw_reconf_flags) { | 351 | if (hw_reconf_flags) |
333 | ieee80211_hw_config(local, hw_reconf_flags); | 352 | ieee80211_hw_config(local, hw_reconf_flags); |
334 | /* | ||
335 | * set default queue parameters so drivers don't | ||
336 | * need to initialise the hardware if the hardware | ||
337 | * doesn't start up with sane defaults | ||
338 | */ | ||
339 | ieee80211_set_wmm_default(sdata); | ||
340 | } | ||
341 | 353 | ||
342 | ieee80211_recalc_ps(local, -1); | 354 | ieee80211_recalc_ps(local, -1); |
343 | 355 | ||
@@ -345,7 +357,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
345 | 357 | ||
346 | return 0; | 358 | return 0; |
347 | err_del_interface: | 359 | err_del_interface: |
348 | drv_remove_interface(local, &sdata->vif); | 360 | drv_remove_interface(local, sdata); |
349 | err_stop: | 361 | err_stop: |
350 | if (!local->open_count) | 362 | if (!local->open_count) |
351 | drv_stop(local); | 363 | drv_stop(local); |
@@ -450,15 +462,19 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
450 | struct ieee80211_sub_if_data *vlan, *tmpsdata; | 462 | struct ieee80211_sub_if_data *vlan, *tmpsdata; |
451 | struct beacon_data *old_beacon = | 463 | struct beacon_data *old_beacon = |
452 | rtnl_dereference(sdata->u.ap.beacon); | 464 | rtnl_dereference(sdata->u.ap.beacon); |
465 | struct sk_buff *old_probe_resp = | ||
466 | rtnl_dereference(sdata->u.ap.probe_resp); | ||
453 | 467 | ||
454 | /* sdata_running will return false, so this will disable */ | 468 | /* sdata_running will return false, so this will disable */ |
455 | ieee80211_bss_info_change_notify(sdata, | 469 | ieee80211_bss_info_change_notify(sdata, |
456 | BSS_CHANGED_BEACON_ENABLED); | 470 | BSS_CHANGED_BEACON_ENABLED); |
457 | 471 | ||
458 | /* remove beacon */ | 472 | /* remove beacon and probe response */ |
459 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); | 473 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); |
474 | RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); | ||
460 | synchronize_rcu(); | 475 | synchronize_rcu(); |
461 | kfree(old_beacon); | 476 | kfree(old_beacon); |
477 | kfree(old_probe_resp); | ||
462 | 478 | ||
463 | /* down all dependent devices, that is VLANs */ | 479 | /* down all dependent devices, that is VLANs */ |
464 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, | 480 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, |
@@ -520,7 +536,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
520 | ieee80211_free_keys(sdata); | 536 | ieee80211_free_keys(sdata); |
521 | 537 | ||
522 | if (going_down) | 538 | if (going_down) |
523 | drv_remove_interface(local, &sdata->vif); | 539 | drv_remove_interface(local, sdata); |
524 | } | 540 | } |
525 | 541 | ||
526 | sdata->bss = NULL; | 542 | sdata->bss = NULL; |