|
@@ -3225,7 +3225,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|
|
{
|
|
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
|
|
struct ieee80211_local *local = sdata->local;
|
|
|
- struct ieee80211_chanctx_conf *chanctx_conf;
|
|
|
+ struct ieee80211_chanctx_conf *conf;
|
|
|
struct ieee80211_chanctx *chanctx;
|
|
|
int err, num_chanctx, changed = 0;
|
|
|
|
|
@@ -3241,23 +3241,24 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|
|
&sdata->vif.bss_conf.chandef))
|
|
|
return -EINVAL;
|
|
|
|
|
|
- rcu_read_lock();
|
|
|
- chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
|
|
- if (!chanctx_conf) {
|
|
|
- rcu_read_unlock();
|
|
|
+ mutex_lock(&local->chanctx_mtx);
|
|
|
+ conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
|
|
|
+ lockdep_is_held(&local->chanctx_mtx));
|
|
|
+ if (!conf) {
|
|
|
+ mutex_unlock(&local->chanctx_mtx);
|
|
|
return -EBUSY;
|
|
|
}
|
|
|
|
|
|
/* don't handle for multi-VIF cases */
|
|
|
- chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
|
|
|
+ chanctx = container_of(conf, struct ieee80211_chanctx, conf);
|
|
|
if (chanctx->refcount > 1) {
|
|
|
- rcu_read_unlock();
|
|
|
+ mutex_unlock(&local->chanctx_mtx);
|
|
|
return -EBUSY;
|
|
|
}
|
|
|
num_chanctx = 0;
|
|
|
list_for_each_entry_rcu(chanctx, &local->chanctx_list, list)
|
|
|
num_chanctx++;
|
|
|
- rcu_read_unlock();
|
|
|
+ mutex_unlock(&local->chanctx_mtx);
|
|
|
|
|
|
if (num_chanctx > 1)
|
|
|
return -EBUSY;
|