|
@@ -788,18 +788,10 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|
struct cfg80211_csa_settings params;
|
|
struct cfg80211_csa_settings params;
|
|
struct ieee80211_csa_ie csa_ie;
|
|
struct ieee80211_csa_ie csa_ie;
|
|
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
|
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
|
- struct ieee80211_chanctx_conf *chanctx_conf;
|
|
|
|
- struct ieee80211_chanctx *chanctx;
|
|
|
|
enum nl80211_channel_type ch_type;
|
|
enum nl80211_channel_type ch_type;
|
|
- int err, num_chanctx;
|
|
|
|
|
|
+ int err;
|
|
u32 sta_flags;
|
|
u32 sta_flags;
|
|
|
|
|
|
- if (sdata->vif.csa_active)
|
|
|
|
- return true;
|
|
|
|
-
|
|
|
|
- if (!sdata->vif.bss_conf.ibss_joined)
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
sta_flags = IEEE80211_STA_DISABLE_VHT;
|
|
sta_flags = IEEE80211_STA_DISABLE_VHT;
|
|
switch (ifibss->chandef.width) {
|
|
switch (ifibss->chandef.width) {
|
|
case NL80211_CHAN_WIDTH_5:
|
|
case NL80211_CHAN_WIDTH_5:
|
|
@@ -834,9 +826,6 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|
params.count = csa_ie.count;
|
|
params.count = csa_ie.count;
|
|
params.chandef = csa_ie.chandef;
|
|
params.chandef = csa_ie.chandef;
|
|
|
|
|
|
- if (ifibss->chandef.chan->band != params.chandef.chan->band)
|
|
|
|
- goto disconnect;
|
|
|
|
-
|
|
|
|
switch (ifibss->chandef.width) {
|
|
switch (ifibss->chandef.width) {
|
|
case NL80211_CHAN_WIDTH_20_NOHT:
|
|
case NL80211_CHAN_WIDTH_20_NOHT:
|
|
case NL80211_CHAN_WIDTH_20:
|
|
case NL80211_CHAN_WIDTH_20:
|
|
@@ -892,28 +881,12 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|
params.radar_required = true;
|
|
params.radar_required = true;
|
|
}
|
|
}
|
|
|
|
|
|
- rcu_read_lock();
|
|
|
|
- chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
|
|
|
- if (!chanctx_conf) {
|
|
|
|
- rcu_read_unlock();
|
|
|
|
- goto disconnect;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* don't handle for multi-VIF cases */
|
|
|
|
- chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
|
|
|
|
- if (chanctx->refcount > 1) {
|
|
|
|
- rcu_read_unlock();
|
|
|
|
- goto disconnect;
|
|
|
|
- }
|
|
|
|
- num_chanctx = 0;
|
|
|
|
- list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list)
|
|
|
|
- num_chanctx++;
|
|
|
|
-
|
|
|
|
- if (num_chanctx > 1) {
|
|
|
|
- rcu_read_unlock();
|
|
|
|
- goto disconnect;
|
|
|
|
|
|
+ if (cfg80211_chandef_identical(¶ms.chandef,
|
|
|
|
+ &sdata->vif.bss_conf.chandef)) {
|
|
|
|
+ ibss_dbg(sdata,
|
|
|
|
+ "received csa with an identical chandef, ignoring\n");
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
- rcu_read_unlock();
|
|
|
|
|
|
|
|
/* all checks done, now perform the channel switch. */
|
|
/* all checks done, now perform the channel switch. */
|
|
ibss_dbg(sdata,
|
|
ibss_dbg(sdata,
|
|
@@ -922,19 +895,9 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
|
params.block_tx = !!csa_ie.mode;
|
|
params.block_tx = !!csa_ie.mode;
|
|
|
|
|
|
- ieee80211_ibss_csa_beacon(sdata, ¶ms);
|
|
|
|
- sdata->csa_radar_required = params.radar_required;
|
|
|
|
-
|
|
|
|
- if (params.block_tx)
|
|
|
|
- ieee80211_stop_queues_by_reason(&sdata->local->hw,
|
|
|
|
- IEEE80211_MAX_QUEUE_MAP,
|
|
|
|
- IEEE80211_QUEUE_STOP_REASON_CSA);
|
|
|
|
-
|
|
|
|
- sdata->csa_chandef = params.chandef;
|
|
|
|
- sdata->vif.csa_active = true;
|
|
|
|
-
|
|
|
|
- ieee80211_bss_info_change_notify(sdata, err);
|
|
|
|
- drv_channel_switch_beacon(sdata, ¶ms.chandef);
|
|
|
|
|
|
+ if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev,
|
|
|
|
+ ¶ms))
|
|
|
|
+ goto disconnect;
|
|
|
|
|
|
ieee80211_ibss_csa_mark_radar(sdata);
|
|
ieee80211_ibss_csa_mark_radar(sdata);
|
|
|
|
|
|
@@ -970,7 +933,8 @@ ieee80211_rx_mgmt_spectrum_mgmt(struct ieee80211_sub_if_data *sdata,
|
|
if (len < required_len)
|
|
if (len < required_len)
|
|
return;
|
|
return;
|
|
|
|
|
|
- ieee80211_ibss_process_chanswitch(sdata, elems, false);
|
|
|
|
|
|
+ if (!sdata->vif.csa_active)
|
|
|
|
+ ieee80211_ibss_process_chanswitch(sdata, elems, false);
|
|
}
|
|
}
|
|
|
|
|
|
static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata,
|
|
static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata,
|
|
@@ -1151,7 +1115,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
|
goto put_bss;
|
|
goto put_bss;
|
|
|
|
|
|
/* process channel switch */
|
|
/* process channel switch */
|
|
- if (ieee80211_ibss_process_chanswitch(sdata, elems, true))
|
|
|
|
|
|
+ if (sdata->vif.csa_active ||
|
|
|
|
+ ieee80211_ibss_process_chanswitch(sdata, elems, true))
|
|
goto put_bss;
|
|
goto put_bss;
|
|
|
|
|
|
/* same BSSID */
|
|
/* same BSSID */
|