diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 21 |
1 files changed, 11 insertions, 10 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 906fc2be0cfb..56167a3d872d 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -465,21 +465,11 @@ static int ieee80211_stop(struct net_device *dev) | |||
465 | cancel_work_sync(&sdata->u.mgd.monitor_work); | 465 | cancel_work_sync(&sdata->u.mgd.monitor_work); |
466 | cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work); | 466 | cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work); |
467 | 467 | ||
468 | /* | ||
469 | * When we get here, the interface is marked down. | ||
470 | * Call synchronize_rcu() to wait for the RX path | ||
471 | * should it be using the interface and enqueuing | ||
472 | * frames at this very time on another CPU. | ||
473 | */ | ||
474 | synchronize_rcu(); | ||
475 | skb_queue_purge(&sdata->u.mgd.skb_queue); | ||
476 | /* fall through */ | 468 | /* fall through */ |
477 | case NL80211_IFTYPE_ADHOC: | 469 | case NL80211_IFTYPE_ADHOC: |
478 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 470 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
479 | del_timer_sync(&sdata->u.ibss.timer); | 471 | del_timer_sync(&sdata->u.ibss.timer); |
480 | cancel_work_sync(&sdata->u.ibss.work); | 472 | cancel_work_sync(&sdata->u.ibss.work); |
481 | synchronize_rcu(); | ||
482 | skb_queue_purge(&sdata->u.ibss.skb_queue); | ||
483 | } | 473 | } |
484 | /* fall through */ | 474 | /* fall through */ |
485 | case NL80211_IFTYPE_MESH_POINT: | 475 | case NL80211_IFTYPE_MESH_POINT: |
@@ -495,6 +485,15 @@ static int ieee80211_stop(struct net_device *dev) | |||
495 | } | 485 | } |
496 | /* fall through */ | 486 | /* fall through */ |
497 | default: | 487 | default: |
488 | /* | ||
489 | * When we get here, the interface is marked down. | ||
490 | * Call synchronize_rcu() to wait for the RX path | ||
491 | * should it be using the interface and enqueuing | ||
492 | * frames at this very time on another CPU. | ||
493 | */ | ||
494 | synchronize_rcu(); | ||
495 | skb_queue_purge(&sdata->skb_queue); | ||
496 | |||
498 | if (local->scan_sdata == sdata) | 497 | if (local->scan_sdata == sdata) |
499 | ieee80211_scan_cancel(local); | 498 | ieee80211_scan_cancel(local); |
500 | 499 | ||
@@ -721,6 +720,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
721 | /* only monitor differs */ | 720 | /* only monitor differs */ |
722 | sdata->dev->type = ARPHRD_ETHER; | 721 | sdata->dev->type = ARPHRD_ETHER; |
723 | 722 | ||
723 | skb_queue_head_init(&sdata->skb_queue); | ||
724 | |||
724 | switch (type) { | 725 | switch (type) { |
725 | case NL80211_IFTYPE_AP: | 726 | case NL80211_IFTYPE_AP: |
726 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); | 727 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); |