diff options
Diffstat (limited to 'net/mac80211/iface.c')
| -rw-r--r-- | net/mac80211/iface.c | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 3dfd20a453ab..ce1c44370610 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
| @@ -418,20 +418,24 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
| 418 | return ret; | 418 | return ret; |
| 419 | } | 419 | } |
| 420 | 420 | ||
| 421 | mutex_lock(&local->iflist_mtx); | ||
| 422 | rcu_assign_pointer(local->monitor_sdata, sdata); | ||
| 423 | mutex_unlock(&local->iflist_mtx); | ||
| 424 | |||
| 421 | mutex_lock(&local->mtx); | 425 | mutex_lock(&local->mtx); |
| 422 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, | 426 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, |
| 423 | IEEE80211_CHANCTX_EXCLUSIVE); | 427 | IEEE80211_CHANCTX_EXCLUSIVE); |
| 424 | mutex_unlock(&local->mtx); | 428 | mutex_unlock(&local->mtx); |
| 425 | if (ret) { | 429 | if (ret) { |
| 430 | mutex_lock(&local->iflist_mtx); | ||
| 431 | rcu_assign_pointer(local->monitor_sdata, NULL); | ||
| 432 | mutex_unlock(&local->iflist_mtx); | ||
| 433 | synchronize_net(); | ||
| 426 | drv_remove_interface(local, sdata); | 434 | drv_remove_interface(local, sdata); |
| 427 | kfree(sdata); | 435 | kfree(sdata); |
| 428 | return ret; | 436 | return ret; |
| 429 | } | 437 | } |
| 430 | 438 | ||
| 431 | mutex_lock(&local->iflist_mtx); | ||
| 432 | rcu_assign_pointer(local->monitor_sdata, sdata); | ||
| 433 | mutex_unlock(&local->iflist_mtx); | ||
| 434 | |||
| 435 | return 0; | 439 | return 0; |
| 436 | } | 440 | } |
| 437 | 441 | ||
| @@ -770,12 +774,19 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
| 770 | 774 | ||
| 771 | ieee80211_roc_purge(local, sdata); | 775 | ieee80211_roc_purge(local, sdata); |
| 772 | 776 | ||
| 773 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 777 | switch (sdata->vif.type) { |
| 778 | case NL80211_IFTYPE_STATION: | ||
| 774 | ieee80211_mgd_stop(sdata); | 779 | ieee80211_mgd_stop(sdata); |
| 775 | 780 | break; | |
| 776 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 781 | case NL80211_IFTYPE_ADHOC: |
| 777 | ieee80211_ibss_stop(sdata); | 782 | ieee80211_ibss_stop(sdata); |
| 778 | 783 | break; | |
| 784 | case NL80211_IFTYPE_AP: | ||
| 785 | cancel_work_sync(&sdata->u.ap.request_smps_work); | ||
| 786 | break; | ||
| 787 | default: | ||
| 788 | break; | ||
| 789 | } | ||
| 779 | 790 | ||
| 780 | /* | 791 | /* |
| 781 | * Remove all stations associated with this interface. | 792 | * Remove all stations associated with this interface. |
| @@ -1046,7 +1057,8 @@ static void ieee80211_uninit(struct net_device *dev) | |||
| 1046 | 1057 | ||
| 1047 | static u16 ieee80211_netdev_select_queue(struct net_device *dev, | 1058 | static u16 ieee80211_netdev_select_queue(struct net_device *dev, |
| 1048 | struct sk_buff *skb, | 1059 | struct sk_buff *skb, |
| 1049 | void *accel_priv) | 1060 | void *accel_priv, |
| 1061 | select_queue_fallback_t fallback) | ||
| 1050 | { | 1062 | { |
| 1051 | return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); | 1063 | return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); |
| 1052 | } | 1064 | } |
| @@ -1064,7 +1076,8 @@ static const struct net_device_ops ieee80211_dataif_ops = { | |||
| 1064 | 1076 | ||
| 1065 | static u16 ieee80211_monitor_select_queue(struct net_device *dev, | 1077 | static u16 ieee80211_monitor_select_queue(struct net_device *dev, |
| 1066 | struct sk_buff *skb, | 1078 | struct sk_buff *skb, |
| 1067 | void *accel_priv) | 1079 | void *accel_priv, |
| 1080 | select_queue_fallback_t fallback) | ||
| 1068 | { | 1081 | { |
| 1069 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1082 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 1070 | struct ieee80211_local *local = sdata->local; | 1083 | struct ieee80211_local *local = sdata->local; |
