diff options
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 | ||||
-rw-r--r-- | include/net/cfg80211.h | 3 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 21 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 9 |
4 files changed, 22 insertions, 13 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 36dc61da8336..fd4c89df67e1 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -1109,7 +1109,9 @@ void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, | |||
1109 | (mode == WMI_11G_HT20) ? | 1109 | (mode == WMI_11G_HT20) ? |
1110 | NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT); | 1110 | NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT); |
1111 | 1111 | ||
1112 | mutex_lock(&vif->wdev.mtx); | ||
1112 | cfg80211_ch_switch_notify(vif->ndev, &chandef); | 1113 | cfg80211_ch_switch_notify(vif->ndev, &chandef); |
1114 | mutex_unlock(&vif->wdev.mtx); | ||
1113 | } | 1115 | } |
1114 | 1116 | ||
1115 | static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | 1117 | static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 6c2bc329a900..e9abc7b536cd 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -4286,7 +4286,8 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | |||
4286 | * @dev: the device which switched channels | 4286 | * @dev: the device which switched channels |
4287 | * @chandef: the new channel definition | 4287 | * @chandef: the new channel definition |
4288 | * | 4288 | * |
4289 | * Acquires wdev_lock, so must only be called from sleepable driver context! | 4289 | * Caller must acquire wdev_lock, therefore must only be called from sleepable |
4290 | * driver context! | ||
4290 | */ | 4291 | */ |
4291 | void cfg80211_ch_switch_notify(struct net_device *dev, | 4292 | void cfg80211_ch_switch_notify(struct net_device *dev, |
4292 | struct cfg80211_chan_def *chandef); | 4293 | struct cfg80211_chan_def *chandef); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 4a5c21ed64d1..1d446ac97ab5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -2988,13 +2988,18 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
2988 | struct ieee80211_local *local = sdata->local; | 2988 | struct ieee80211_local *local = sdata->local; |
2989 | int err, changed = 0; | 2989 | int err, changed = 0; |
2990 | 2990 | ||
2991 | sdata_lock(sdata); | ||
2992 | /* AP might have been stopped while waiting for the lock. */ | ||
2993 | if (!sdata->vif.csa_active) | ||
2994 | goto unlock; | ||
2995 | |||
2991 | if (!ieee80211_sdata_running(sdata)) | 2996 | if (!ieee80211_sdata_running(sdata)) |
2992 | return; | 2997 | goto unlock; |
2993 | 2998 | ||
2994 | sdata->radar_required = sdata->csa_radar_required; | 2999 | sdata->radar_required = sdata->csa_radar_required; |
2995 | err = ieee80211_vif_change_channel(sdata, &changed); | 3000 | err = ieee80211_vif_change_channel(sdata, &changed); |
2996 | if (WARN_ON(err < 0)) | 3001 | if (WARN_ON(err < 0)) |
2997 | return; | 3002 | goto unlock; |
2998 | 3003 | ||
2999 | if (!local->use_chanctx) { | 3004 | if (!local->use_chanctx) { |
3000 | local->_oper_chandef = sdata->csa_chandef; | 3005 | local->_oper_chandef = sdata->csa_chandef; |
@@ -3003,11 +3008,13 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
3003 | 3008 | ||
3004 | ieee80211_bss_info_change_notify(sdata, changed); | 3009 | ieee80211_bss_info_change_notify(sdata, changed); |
3005 | 3010 | ||
3011 | sdata->vif.csa_active = false; | ||
3006 | switch (sdata->vif.type) { | 3012 | switch (sdata->vif.type) { |
3007 | case NL80211_IFTYPE_AP: | 3013 | case NL80211_IFTYPE_AP: |
3008 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); | 3014 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); |
3009 | if (err < 0) | 3015 | if (err < 0) |
3010 | return; | 3016 | goto unlock; |
3017 | |||
3011 | changed |= err; | 3018 | changed |= err; |
3012 | kfree(sdata->u.ap.next_beacon); | 3019 | kfree(sdata->u.ap.next_beacon); |
3013 | sdata->u.ap.next_beacon = NULL; | 3020 | sdata->u.ap.next_beacon = NULL; |
@@ -3021,20 +3028,22 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
3021 | case NL80211_IFTYPE_MESH_POINT: | 3028 | case NL80211_IFTYPE_MESH_POINT: |
3022 | err = ieee80211_mesh_finish_csa(sdata); | 3029 | err = ieee80211_mesh_finish_csa(sdata); |
3023 | if (err < 0) | 3030 | if (err < 0) |
3024 | return; | 3031 | goto unlock; |
3025 | break; | 3032 | break; |
3026 | #endif | 3033 | #endif |
3027 | default: | 3034 | default: |
3028 | WARN_ON(1); | 3035 | WARN_ON(1); |
3029 | return; | 3036 | goto unlock; |
3030 | } | 3037 | } |
3031 | sdata->vif.csa_active = false; | ||
3032 | 3038 | ||
3033 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 3039 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
3034 | IEEE80211_MAX_QUEUE_MAP, | 3040 | IEEE80211_MAX_QUEUE_MAP, |
3035 | IEEE80211_QUEUE_STOP_REASON_CSA); | 3041 | IEEE80211_QUEUE_STOP_REASON_CSA); |
3036 | 3042 | ||
3037 | cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); | 3043 | cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); |
3044 | |||
3045 | unlock: | ||
3046 | sdata_unlock(sdata); | ||
3038 | } | 3047 | } |
3039 | 3048 | ||
3040 | static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | 3049 | static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 398756c226c3..95882a788b5b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -10821,21 +10821,18 @@ void cfg80211_ch_switch_notify(struct net_device *dev, | |||
10821 | struct wiphy *wiphy = wdev->wiphy; | 10821 | struct wiphy *wiphy = wdev->wiphy; |
10822 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 10822 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
10823 | 10823 | ||
10824 | trace_cfg80211_ch_switch_notify(dev, chandef); | 10824 | ASSERT_WDEV_LOCK(wdev); |
10825 | 10825 | ||
10826 | wdev_lock(wdev); | 10826 | trace_cfg80211_ch_switch_notify(dev, chandef); |
10827 | 10827 | ||
10828 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | 10828 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && |
10829 | wdev->iftype != NL80211_IFTYPE_P2P_GO && | 10829 | wdev->iftype != NL80211_IFTYPE_P2P_GO && |
10830 | wdev->iftype != NL80211_IFTYPE_ADHOC && | 10830 | wdev->iftype != NL80211_IFTYPE_ADHOC && |
10831 | wdev->iftype != NL80211_IFTYPE_MESH_POINT)) | 10831 | wdev->iftype != NL80211_IFTYPE_MESH_POINT)) |
10832 | goto out; | 10832 | return; |
10833 | 10833 | ||
10834 | wdev->channel = chandef->chan; | 10834 | wdev->channel = chandef->chan; |
10835 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); | 10835 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); |
10836 | out: | ||
10837 | wdev_unlock(wdev); | ||
10838 | return; | ||
10839 | } | 10836 | } |
10840 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); | 10837 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); |
10841 | 10838 | ||