diff options
author | Johannes Berg <johannes.berg@intel.com> | 2013-04-22 09:31:43 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-04-22 09:31:43 -0400 |
commit | a42c74ee608a424342ef7069ccddf196d873040c (patch) | |
tree | 75adfb9f5e06ebb7c7d5d5e5a5408fa0d6d504b9 /net/mac80211 | |
parent | 97990a060e6757f48b931a3946b17c1c4362c3fb (diff) | |
parent | 9b383672452bb1097124c76fcb4903e0021f6baf (diff) |
Merge remote-tracking branch 'wireless-next/master' into mac80211-next
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 6 | ||||
-rw-r--r-- | net/mac80211/chan.c | 17 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 4 | ||||
-rw-r--r-- | net/mac80211/iface.c | 37 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 3 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 6 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 23 | ||||
-rw-r--r-- | net/mac80211/rx.c | 14 |
8 files changed, 77 insertions, 33 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 72ab1c0e3ca7..490990e3fc38 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -2661,7 +2661,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2661 | list_del(&dep->list); | 2661 | list_del(&dep->list); |
2662 | mutex_unlock(&local->mtx); | 2662 | mutex_unlock(&local->mtx); |
2663 | 2663 | ||
2664 | ieee80211_roc_notify_destroy(dep); | 2664 | ieee80211_roc_notify_destroy(dep, true); |
2665 | return 0; | 2665 | return 0; |
2666 | } | 2666 | } |
2667 | 2667 | ||
@@ -2701,7 +2701,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2701 | ieee80211_start_next_roc(local); | 2701 | ieee80211_start_next_roc(local); |
2702 | mutex_unlock(&local->mtx); | 2702 | mutex_unlock(&local->mtx); |
2703 | 2703 | ||
2704 | ieee80211_roc_notify_destroy(found); | 2704 | ieee80211_roc_notify_destroy(found, true); |
2705 | } else { | 2705 | } else { |
2706 | /* work may be pending so use it all the time */ | 2706 | /* work may be pending so use it all the time */ |
2707 | found->abort = true; | 2707 | found->abort = true; |
@@ -2711,6 +2711,8 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2711 | 2711 | ||
2712 | /* work will clean up etc */ | 2712 | /* work will clean up etc */ |
2713 | flush_delayed_work(&found->work); | 2713 | flush_delayed_work(&found->work); |
2714 | WARN_ON(!found->to_be_freed); | ||
2715 | kfree(found); | ||
2714 | } | 2716 | } |
2715 | 2717 | ||
2716 | return 0; | 2718 | return 0; |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 166165efd8e2..03e8d2e3270e 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -79,6 +79,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
79 | enum ieee80211_chanctx_mode mode) | 79 | enum ieee80211_chanctx_mode mode) |
80 | { | 80 | { |
81 | struct ieee80211_chanctx *ctx; | 81 | struct ieee80211_chanctx *ctx; |
82 | u32 changed; | ||
82 | int err; | 83 | int err; |
83 | 84 | ||
84 | lockdep_assert_held(&local->chanctx_mtx); | 85 | lockdep_assert_held(&local->chanctx_mtx); |
@@ -95,6 +96,13 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
95 | if (!local->use_chanctx) | 96 | if (!local->use_chanctx) |
96 | local->hw.conf.radar_enabled = ctx->conf.radar_enabled; | 97 | local->hw.conf.radar_enabled = ctx->conf.radar_enabled; |
97 | 98 | ||
99 | /* acquire mutex to prevent idle from changing */ | ||
100 | mutex_lock(&local->mtx); | ||
101 | /* turn idle off *before* setting channel -- some drivers need that */ | ||
102 | changed = ieee80211_idle_off(local); | ||
103 | if (changed) | ||
104 | ieee80211_hw_config(local, changed); | ||
105 | |||
98 | if (!local->use_chanctx) { | 106 | if (!local->use_chanctx) { |
99 | local->_oper_chandef = *chandef; | 107 | local->_oper_chandef = *chandef; |
100 | ieee80211_hw_config(local, 0); | 108 | ieee80211_hw_config(local, 0); |
@@ -102,14 +110,17 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
102 | err = drv_add_chanctx(local, ctx); | 110 | err = drv_add_chanctx(local, ctx); |
103 | if (err) { | 111 | if (err) { |
104 | kfree(ctx); | 112 | kfree(ctx); |
105 | return ERR_PTR(err); | 113 | ctx = ERR_PTR(err); |
114 | |||
115 | ieee80211_recalc_idle(local); | ||
116 | goto out; | ||
106 | } | 117 | } |
107 | } | 118 | } |
108 | 119 | ||
120 | /* and keep the mutex held until the new chanctx is on the list */ | ||
109 | list_add_rcu(&ctx->list, &local->chanctx_list); | 121 | list_add_rcu(&ctx->list, &local->chanctx_list); |
110 | 122 | ||
111 | mutex_lock(&local->mtx); | 123 | out: |
112 | ieee80211_recalc_idle(local); | ||
113 | mutex_unlock(&local->mtx); | 124 | mutex_unlock(&local->mtx); |
114 | 125 | ||
115 | return ctx; | 126 | return ctx; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 21c1720eee00..af8410e1291e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -309,6 +309,7 @@ struct ieee80211_roc_work { | |||
309 | struct ieee80211_channel *chan; | 309 | struct ieee80211_channel *chan; |
310 | 310 | ||
311 | bool started, abort, hw_begun, notified; | 311 | bool started, abort, hw_begun, notified; |
312 | bool to_be_freed; | ||
312 | 313 | ||
313 | unsigned long hw_start_time; | 314 | unsigned long hw_start_time; |
314 | 315 | ||
@@ -1318,7 +1319,7 @@ void ieee80211_roc_setup(struct ieee80211_local *local); | |||
1318 | void ieee80211_start_next_roc(struct ieee80211_local *local); | 1319 | void ieee80211_start_next_roc(struct ieee80211_local *local); |
1319 | void ieee80211_roc_purge(struct ieee80211_local *local, | 1320 | void ieee80211_roc_purge(struct ieee80211_local *local, |
1320 | struct ieee80211_sub_if_data *sdata); | 1321 | struct ieee80211_sub_if_data *sdata); |
1321 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc); | 1322 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free); |
1322 | void ieee80211_sw_roc_work(struct work_struct *work); | 1323 | void ieee80211_sw_roc_work(struct work_struct *work); |
1323 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); | 1324 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); |
1324 | 1325 | ||
@@ -1332,6 +1333,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
1332 | enum nl80211_iftype type); | 1333 | enum nl80211_iftype type); |
1333 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); | 1334 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); |
1334 | void ieee80211_remove_interfaces(struct ieee80211_local *local); | 1335 | void ieee80211_remove_interfaces(struct ieee80211_local *local); |
1336 | u32 ieee80211_idle_off(struct ieee80211_local *local); | ||
1335 | void ieee80211_recalc_idle(struct ieee80211_local *local); | 1337 | void ieee80211_recalc_idle(struct ieee80211_local *local); |
1336 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, | 1338 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, |
1337 | const int offset); | 1339 | const int offset); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index b6abaaa3676f..146b1320af4e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -78,7 +78,7 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) | |||
78 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); | 78 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); |
79 | } | 79 | } |
80 | 80 | ||
81 | static u32 ieee80211_idle_off(struct ieee80211_local *local) | 81 | u32 ieee80211_idle_off(struct ieee80211_local *local) |
82 | { | 82 | { |
83 | if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) | 83 | if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) |
84 | return 0; | 84 | return 0; |
@@ -349,21 +349,19 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) | |||
349 | int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | 349 | int ieee80211_add_virtual_monitor(struct ieee80211_local *local) |
350 | { | 350 | { |
351 | struct ieee80211_sub_if_data *sdata; | 351 | struct ieee80211_sub_if_data *sdata; |
352 | int ret = 0; | 352 | int ret; |
353 | 353 | ||
354 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) | 354 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) |
355 | return 0; | 355 | return 0; |
356 | 356 | ||
357 | mutex_lock(&local->iflist_mtx); | 357 | ASSERT_RTNL(); |
358 | 358 | ||
359 | if (local->monitor_sdata) | 359 | if (local->monitor_sdata) |
360 | goto out_unlock; | 360 | return 0; |
361 | 361 | ||
362 | sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); | 362 | sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); |
363 | if (!sdata) { | 363 | if (!sdata) |
364 | ret = -ENOMEM; | 364 | return -ENOMEM; |
365 | goto out_unlock; | ||
366 | } | ||
367 | 365 | ||
368 | /* set up data */ | 366 | /* set up data */ |
369 | sdata->local = local; | 367 | sdata->local = local; |
@@ -377,13 +375,13 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
377 | if (WARN_ON(ret)) { | 375 | if (WARN_ON(ret)) { |
378 | /* ok .. stupid driver, it asked for this! */ | 376 | /* ok .. stupid driver, it asked for this! */ |
379 | kfree(sdata); | 377 | kfree(sdata); |
380 | goto out_unlock; | 378 | return ret; |
381 | } | 379 | } |
382 | 380 | ||
383 | ret = ieee80211_check_queues(sdata); | 381 | ret = ieee80211_check_queues(sdata); |
384 | if (ret) { | 382 | if (ret) { |
385 | kfree(sdata); | 383 | kfree(sdata); |
386 | goto out_unlock; | 384 | return ret; |
387 | } | 385 | } |
388 | 386 | ||
389 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, | 387 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, |
@@ -391,13 +389,14 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
391 | if (ret) { | 389 | if (ret) { |
392 | drv_remove_interface(local, sdata); | 390 | drv_remove_interface(local, sdata); |
393 | kfree(sdata); | 391 | kfree(sdata); |
394 | goto out_unlock; | 392 | return ret; |
395 | } | 393 | } |
396 | 394 | ||
395 | mutex_lock(&local->iflist_mtx); | ||
397 | rcu_assign_pointer(local->monitor_sdata, sdata); | 396 | rcu_assign_pointer(local->monitor_sdata, sdata); |
398 | out_unlock: | ||
399 | mutex_unlock(&local->iflist_mtx); | 397 | mutex_unlock(&local->iflist_mtx); |
400 | return ret; | 398 | |
399 | return 0; | ||
401 | } | 400 | } |
402 | 401 | ||
403 | void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | 402 | void ieee80211_del_virtual_monitor(struct ieee80211_local *local) |
@@ -407,14 +406,20 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
407 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) | 406 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) |
408 | return; | 407 | return; |
409 | 408 | ||
409 | ASSERT_RTNL(); | ||
410 | |||
410 | mutex_lock(&local->iflist_mtx); | 411 | mutex_lock(&local->iflist_mtx); |
411 | 412 | ||
412 | sdata = rcu_dereference_protected(local->monitor_sdata, | 413 | sdata = rcu_dereference_protected(local->monitor_sdata, |
413 | lockdep_is_held(&local->iflist_mtx)); | 414 | lockdep_is_held(&local->iflist_mtx)); |
414 | if (!sdata) | 415 | if (!sdata) { |
415 | goto out_unlock; | 416 | mutex_unlock(&local->iflist_mtx); |
417 | return; | ||
418 | } | ||
416 | 419 | ||
417 | rcu_assign_pointer(local->monitor_sdata, NULL); | 420 | rcu_assign_pointer(local->monitor_sdata, NULL); |
421 | mutex_unlock(&local->iflist_mtx); | ||
422 | |||
418 | synchronize_net(); | 423 | synchronize_net(); |
419 | 424 | ||
420 | ieee80211_vif_release_channel(sdata); | 425 | ieee80211_vif_release_channel(sdata); |
@@ -422,8 +427,6 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
422 | drv_remove_interface(local, sdata); | 427 | drv_remove_interface(local, sdata); |
423 | 428 | ||
424 | kfree(sdata); | 429 | kfree(sdata); |
425 | out_unlock: | ||
426 | mutex_unlock(&local->iflist_mtx); | ||
427 | } | 430 | } |
428 | 431 | ||
429 | /* | 432 | /* |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 4b984765d62d..6952760881c8 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -1004,7 +1004,8 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | |||
1004 | 1004 | ||
1005 | rcu_read_lock(); | 1005 | rcu_read_lock(); |
1006 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 1006 | list_for_each_entry_rcu(sdata, &local->interfaces, list) |
1007 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1007 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
1008 | ieee80211_sdata_running(sdata)) | ||
1008 | ieee80211_queue_work(&local->hw, &sdata->work); | 1009 | ieee80211_queue_work(&local->hw, &sdata->work); |
1009 | rcu_read_unlock(); | 1010 | rcu_read_unlock(); |
1010 | } | 1011 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c7860d0450dd..f7beb12abde2 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -3665,8 +3665,10 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) | |||
3665 | 3665 | ||
3666 | /* Restart STA timers */ | 3666 | /* Restart STA timers */ |
3667 | rcu_read_lock(); | 3667 | rcu_read_lock(); |
3668 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 3668 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
3669 | ieee80211_restart_sta_timer(sdata); | 3669 | if (ieee80211_sdata_running(sdata)) |
3670 | ieee80211_restart_sta_timer(sdata); | ||
3671 | } | ||
3670 | rcu_read_unlock(); | 3672 | rcu_read_unlock(); |
3671 | } | 3673 | } |
3672 | 3674 | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index e19d6cf26dde..acd1f71adc03 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -297,10 +297,13 @@ void ieee80211_start_next_roc(struct ieee80211_local *local) | |||
297 | } | 297 | } |
298 | } | 298 | } |
299 | 299 | ||
300 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) | 300 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free) |
301 | { | 301 | { |
302 | struct ieee80211_roc_work *dep, *tmp; | 302 | struct ieee80211_roc_work *dep, *tmp; |
303 | 303 | ||
304 | if (WARN_ON(roc->to_be_freed)) | ||
305 | return; | ||
306 | |||
304 | /* was never transmitted */ | 307 | /* was never transmitted */ |
305 | if (roc->frame) { | 308 | if (roc->frame) { |
306 | cfg80211_mgmt_tx_status(&roc->sdata->wdev, | 309 | cfg80211_mgmt_tx_status(&roc->sdata->wdev, |
@@ -316,9 +319,12 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) | |||
316 | GFP_KERNEL); | 319 | GFP_KERNEL); |
317 | 320 | ||
318 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) | 321 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) |
319 | ieee80211_roc_notify_destroy(dep); | 322 | ieee80211_roc_notify_destroy(dep, true); |
320 | 323 | ||
321 | kfree(roc); | 324 | if (free) |
325 | kfree(roc); | ||
326 | else | ||
327 | roc->to_be_freed = true; | ||
322 | } | 328 | } |
323 | 329 | ||
324 | void ieee80211_sw_roc_work(struct work_struct *work) | 330 | void ieee80211_sw_roc_work(struct work_struct *work) |
@@ -331,6 +337,9 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
331 | 337 | ||
332 | mutex_lock(&local->mtx); | 338 | mutex_lock(&local->mtx); |
333 | 339 | ||
340 | if (roc->to_be_freed) | ||
341 | goto out_unlock; | ||
342 | |||
334 | if (roc->abort) | 343 | if (roc->abort) |
335 | goto finish; | 344 | goto finish; |
336 | 345 | ||
@@ -370,7 +379,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
370 | finish: | 379 | finish: |
371 | list_del(&roc->list); | 380 | list_del(&roc->list); |
372 | started = roc->started; | 381 | started = roc->started; |
373 | ieee80211_roc_notify_destroy(roc); | 382 | ieee80211_roc_notify_destroy(roc, !roc->abort); |
374 | 383 | ||
375 | if (started) { | 384 | if (started) { |
376 | ieee80211_flush_queues(local, NULL); | 385 | ieee80211_flush_queues(local, NULL); |
@@ -410,7 +419,7 @@ static void ieee80211_hw_roc_done(struct work_struct *work) | |||
410 | 419 | ||
411 | list_del(&roc->list); | 420 | list_del(&roc->list); |
412 | 421 | ||
413 | ieee80211_roc_notify_destroy(roc); | 422 | ieee80211_roc_notify_destroy(roc, true); |
414 | 423 | ||
415 | /* if there's another roc, start it now */ | 424 | /* if there's another roc, start it now */ |
416 | ieee80211_start_next_roc(local); | 425 | ieee80211_start_next_roc(local); |
@@ -460,12 +469,14 @@ void ieee80211_roc_purge(struct ieee80211_local *local, | |||
460 | list_for_each_entry_safe(roc, tmp, &tmp_list, list) { | 469 | list_for_each_entry_safe(roc, tmp, &tmp_list, list) { |
461 | if (local->ops->remain_on_channel) { | 470 | if (local->ops->remain_on_channel) { |
462 | list_del(&roc->list); | 471 | list_del(&roc->list); |
463 | ieee80211_roc_notify_destroy(roc); | 472 | ieee80211_roc_notify_destroy(roc, true); |
464 | } else { | 473 | } else { |
465 | ieee80211_queue_delayed_work(&local->hw, &roc->work, 0); | 474 | ieee80211_queue_delayed_work(&local->hw, &roc->work, 0); |
466 | 475 | ||
467 | /* work will clean up etc */ | 476 | /* work will clean up etc */ |
468 | flush_delayed_work(&roc->work); | 477 | flush_delayed_work(&roc->work); |
478 | WARN_ON(!roc->to_be_freed); | ||
479 | kfree(roc); | ||
469 | } | 480 | } |
470 | } | 481 | } |
471 | 482 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 14b32a4cd7bb..c8447af76ead 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2679,7 +2679,19 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) | |||
2679 | 2679 | ||
2680 | memset(nskb->cb, 0, sizeof(nskb->cb)); | 2680 | memset(nskb->cb, 0, sizeof(nskb->cb)); |
2681 | 2681 | ||
2682 | ieee80211_tx_skb(rx->sdata, nskb); | 2682 | if (rx->sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) { |
2683 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(nskb); | ||
2684 | |||
2685 | info->flags = IEEE80211_TX_CTL_TX_OFFCHAN | | ||
2686 | IEEE80211_TX_INTFL_OFFCHAN_TX_OK | | ||
2687 | IEEE80211_TX_CTL_NO_CCK_RATE; | ||
2688 | if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) | ||
2689 | info->hw_queue = | ||
2690 | local->hw.offchannel_tx_hw_queue; | ||
2691 | } | ||
2692 | |||
2693 | __ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7, | ||
2694 | status->band); | ||
2683 | } | 2695 | } |
2684 | dev_kfree_skb(rx->skb); | 2696 | dev_kfree_skb(rx->skb); |
2685 | return RX_QUEUED; | 2697 | return RX_QUEUED; |