aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c2
-rw-r--r--include/net/cfg80211.h3
-rw-r--r--net/mac80211/cfg.c21
-rw-r--r--net/wireless/nl80211.c9
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
1115static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, 1117static 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 */
4291void cfg80211_ch_switch_notify(struct net_device *dev, 4292void 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
3045unlock:
3046 sdata_unlock(sdata);
3038} 3047}
3039 3048
3040static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, 3049static 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);
10836out:
10837 wdev_unlock(wdev);
10838 return;
10839} 10836}
10840EXPORT_SYMBOL(cfg80211_ch_switch_notify); 10837EXPORT_SYMBOL(cfg80211_ch_switch_notify);
10841 10838