mac80211: handle channel frequency offset
cfg80211_chan_def and ieee80211_channel recently gained a frequency offset component. Handle this where it makes sense (potentially required by S1G channels). For IBSS, TDLS, CSA, and ROC we return -EOPNOTSUPP if a channel with frequency offset is passed, since they may or may not work. Once someone tests and verifies these commands work on thos types of channels, we can remove that error. join_ocb and join_mesh look harmless because they use a simple ieee80211_vif_use_channel(), which is using an already verified channel, so we let those through. Signed-off-by: Thomas Pedersen <thomas@adapt-ip.com> Link: https://lore.kernel.org/r/20200402011810.22947-4-thomas@adapt-ip.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
934f4c7dd3
commit
b6011960f3
@ -3287,6 +3287,12 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (params->chandef.chan->freq_offset) {
|
||||
/* this may work, but is untested */
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
chanctx = container_of(conf, struct ieee80211_chanctx, conf);
|
||||
|
||||
ch_switch.timestamp = 0;
|
||||
|
@ -533,6 +533,7 @@ static void ieee80211_del_chanctx(struct ieee80211_local *local,
|
||||
struct cfg80211_chan_def *chandef = &local->_oper_chandef;
|
||||
chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||
chandef->center_freq1 = chandef->chan->center_freq;
|
||||
chandef->freq1_offset = chandef->chan->freq_offset;
|
||||
chandef->center_freq2 = 0;
|
||||
|
||||
/* NOTE: Disabling radar is only valid here for
|
||||
|
@ -1758,6 +1758,11 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (params->chandef.chan->freq_offset) {
|
||||
/* this may work, but is untested */
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
|
||||
¶ms->chandef,
|
||||
sdata->wdev.iftype);
|
||||
|
@ -107,13 +107,15 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
|
||||
chandef.chan = local->tmp_channel;
|
||||
chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||
chandef.center_freq1 = chandef.chan->center_freq;
|
||||
chandef.freq1_offset = chandef.chan->freq_offset;
|
||||
} else
|
||||
chandef = local->_oper_chandef;
|
||||
|
||||
WARN(!cfg80211_chandef_valid(&chandef),
|
||||
"control:%d MHz width:%d center: %d/%d MHz",
|
||||
chandef.chan->center_freq, chandef.width,
|
||||
chandef.center_freq1, chandef.center_freq2);
|
||||
"control:%d.%03d MHz width:%d center: %d.%03d/%d MHz",
|
||||
chandef.chan->center_freq, chandef.chan->freq_offset,
|
||||
chandef.width, chandef.center_freq1, chandef.freq1_offset,
|
||||
chandef.center_freq2);
|
||||
|
||||
if (!cfg80211_chandef_identical(&chandef, &local->_oper_chandef))
|
||||
local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
|
||||
|
@ -162,6 +162,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
||||
chandef->chan = channel;
|
||||
chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||
chandef->center_freq1 = channel->center_freq;
|
||||
chandef->freq1_offset = channel->freq_offset;
|
||||
|
||||
if (!ht_oper || !sta_ht_cap.ht_supported) {
|
||||
ret = IEEE80211_STA_DISABLE_HT |
|
||||
@ -396,9 +397,12 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
|
||||
return 0;
|
||||
|
||||
sdata_info(sdata,
|
||||
"AP %pM changed bandwidth, new config is %d MHz, width %d (%d/%d MHz)\n",
|
||||
ifmgd->bssid, chandef.chan->center_freq, chandef.width,
|
||||
chandef.center_freq1, chandef.center_freq2);
|
||||
"AP %pM changed bandwidth, new config is %d.%03d MHz, "
|
||||
"width %d (%d.%03d/%d MHz)\n",
|
||||
ifmgd->bssid, chandef.chan->center_freq,
|
||||
chandef.chan->freq_offset, chandef.width,
|
||||
chandef.center_freq1, chandef.freq1_offset,
|
||||
chandef.center_freq2);
|
||||
|
||||
if (flags != (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |
|
||||
IEEE80211_STA_DISABLE_VHT |
|
||||
@ -1364,10 +1368,14 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||
if (!cfg80211_chandef_usable(local->hw.wiphy, &csa_ie.chandef,
|
||||
IEEE80211_CHAN_DISABLED)) {
|
||||
sdata_info(sdata,
|
||||
"AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
|
||||
"AP %pM switches to unsupported channel "
|
||||
"(%d.%03d MHz, width:%d, CF1/2: %d.%03d/%d MHz), "
|
||||
"disconnecting\n",
|
||||
ifmgd->associated->bssid,
|
||||
csa_ie.chandef.chan->center_freq,
|
||||
csa_ie.chandef.chan->freq_offset,
|
||||
csa_ie.chandef.width, csa_ie.chandef.center_freq1,
|
||||
csa_ie.chandef.freq1_offset,
|
||||
csa_ie.chandef.center_freq2);
|
||||
ieee80211_queue_work(&local->hw,
|
||||
&ifmgd->csa_connection_drop_work);
|
||||
|
@ -557,6 +557,10 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
|
||||
|
||||
lockdep_assert_held(&local->mtx);
|
||||
|
||||
if (channel->freq_offset)
|
||||
/* this may work, but is untested */
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (local->use_chanctx && !local->ops->remain_on_channel)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
@ -896,6 +896,7 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
|
||||
|
||||
local->scan_chandef.chan = chan;
|
||||
local->scan_chandef.center_freq1 = chan->center_freq;
|
||||
local->scan_chandef.freq1_offset = chan->freq_offset;
|
||||
local->scan_chandef.center_freq2 = 0;
|
||||
switch (scan_req->scan_width) {
|
||||
case NL80211_BSS_CHAN_WIDTH_5:
|
||||
|
@ -1566,6 +1566,10 @@ ieee80211_tdls_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||
u32 ch_sw_tm_ie;
|
||||
int ret;
|
||||
|
||||
if (chandef->chan->freq_offset)
|
||||
/* this may work, but is untested */
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&local->sta_mtx);
|
||||
sta = sta_info_get(sdata, addr);
|
||||
if (!sta) {
|
||||
|
@ -37,32 +37,42 @@
|
||||
#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
|
||||
|
||||
#define CHANDEF_ENTRY __field(u32, control_freq) \
|
||||
__field(u32, freq_offset) \
|
||||
__field(u32, chan_width) \
|
||||
__field(u32, center_freq1) \
|
||||
__field(u32, freq1_offset) \
|
||||
__field(u32, center_freq2)
|
||||
#define CHANDEF_ASSIGN(c) \
|
||||
__entry->control_freq = (c) ? ((c)->chan ? (c)->chan->center_freq : 0) : 0; \
|
||||
__entry->freq_offset = (c) ? ((c)->chan ? (c)->chan->freq_offset : 0) : 0; \
|
||||
__entry->chan_width = (c) ? (c)->width : 0; \
|
||||
__entry->center_freq1 = (c) ? (c)->center_freq1 : 0; \
|
||||
__entry->freq1_offset = (c) ? (c)->freq1_offset : 0; \
|
||||
__entry->center_freq2 = (c) ? (c)->center_freq2 : 0;
|
||||
#define CHANDEF_PR_FMT " control:%d MHz width:%d center: %d/%d MHz"
|
||||
#define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \
|
||||
__entry->center_freq1, __entry->center_freq2
|
||||
#define CHANDEF_PR_FMT " control:%d.%03d MHz width:%d center: %d.%03d/%d MHz"
|
||||
#define CHANDEF_PR_ARG __entry->control_freq, __entry->freq_offset, __entry->chan_width, \
|
||||
__entry->center_freq1, __entry->freq1_offset, __entry->center_freq2
|
||||
|
||||
#define MIN_CHANDEF_ENTRY \
|
||||
__field(u32, min_control_freq) \
|
||||
__field(u32, min_freq_offset) \
|
||||
__field(u32, min_chan_width) \
|
||||
__field(u32, min_center_freq1) \
|
||||
__field(u32, min_freq1_offset) \
|
||||
__field(u32, min_center_freq2)
|
||||
|
||||
#define MIN_CHANDEF_ASSIGN(c) \
|
||||
__entry->min_control_freq = (c)->chan ? (c)->chan->center_freq : 0; \
|
||||
__entry->min_freq_offset = (c)->chan ? (c)->chan->freq_offset : 0; \
|
||||
__entry->min_chan_width = (c)->width; \
|
||||
__entry->min_center_freq1 = (c)->center_freq1; \
|
||||
__entry->freq1_offset = (c)->freq1_offset; \
|
||||
__entry->min_center_freq2 = (c)->center_freq2;
|
||||
#define MIN_CHANDEF_PR_FMT " min_control:%d MHz min_width:%d min_center: %d/%d MHz"
|
||||
#define MIN_CHANDEF_PR_ARG __entry->min_control_freq, __entry->min_chan_width, \
|
||||
__entry->min_center_freq1, __entry->min_center_freq2
|
||||
#define MIN_CHANDEF_PR_FMT " min_control:%d.%03d MHz min_width:%d min_center: %d.%03d/%d MHz"
|
||||
#define MIN_CHANDEF_PR_ARG __entry->min_control_freq, __entry->min_freq_offset, \
|
||||
__entry->min_chan_width, \
|
||||
__entry->min_center_freq1, __entry->min_freq1_offset, \
|
||||
__entry->min_center_freq2
|
||||
|
||||
#define CHANCTX_ENTRY CHANDEF_ENTRY \
|
||||
MIN_CHANDEF_ENTRY \
|
||||
@ -412,6 +422,7 @@ TRACE_EVENT(drv_bss_info_changed,
|
||||
__field(s32, cqm_rssi_hyst)
|
||||
__field(u32, channel_width)
|
||||
__field(u32, channel_cfreq1)
|
||||
__field(u32, channel_cfreq1_offset)
|
||||
__dynamic_array(u32, arp_addr_list,
|
||||
info->arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ?
|
||||
IEEE80211_BSS_ARP_ADDR_LIST_LEN :
|
||||
@ -452,6 +463,7 @@ TRACE_EVENT(drv_bss_info_changed,
|
||||
__entry->cqm_rssi_hyst = info->cqm_rssi_hyst;
|
||||
__entry->channel_width = info->chandef.width;
|
||||
__entry->channel_cfreq1 = info->chandef.center_freq1;
|
||||
__entry->channel_cfreq1_offset = info->chandef.freq1_offset;
|
||||
__entry->arp_addr_cnt = info->arp_addr_cnt;
|
||||
memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list,
|
||||
sizeof(u32) * (info->arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ?
|
||||
@ -1223,6 +1235,7 @@ TRACE_EVENT(drv_remain_on_channel,
|
||||
LOCAL_ENTRY
|
||||
VIF_ENTRY
|
||||
__field(int, center_freq)
|
||||
__field(int, freq_offset)
|
||||
__field(unsigned int, duration)
|
||||
__field(u32, type)
|
||||
),
|
||||
@ -1231,14 +1244,16 @@ TRACE_EVENT(drv_remain_on_channel,
|
||||
LOCAL_ASSIGN;
|
||||
VIF_ASSIGN;
|
||||
__entry->center_freq = chan->center_freq;
|
||||
__entry->freq_offset = chan->freq_offset;
|
||||
__entry->duration = duration;
|
||||
__entry->type = type;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
LOCAL_PR_FMT VIF_PR_FMT " freq:%dMHz duration:%dms type=%d",
|
||||
LOCAL_PR_FMT VIF_PR_FMT " freq:%d.%03dMHz duration:%dms type=%d",
|
||||
LOCAL_PR_ARG, VIF_PR_ARG,
|
||||
__entry->center_freq, __entry->duration, __entry->type
|
||||
__entry->center_freq, __entry->freq_offset,
|
||||
__entry->duration, __entry->type
|
||||
)
|
||||
);
|
||||
|
||||
@ -1546,8 +1561,10 @@ struct trace_vif_entry {
|
||||
|
||||
struct trace_chandef_entry {
|
||||
u32 control_freq;
|
||||
u32 freq_offset;
|
||||
u32 chan_width;
|
||||
u32 center_freq1;
|
||||
u32 freq1_offset;
|
||||
u32 center_freq2;
|
||||
} __packed;
|
||||
|
||||
@ -1597,18 +1614,26 @@ TRACE_EVENT(drv_switch_vif_chanctx,
|
||||
sizeof(local_vifs[i].vif.vif_name));
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.control_freq,
|
||||
old_ctx->def.chan->center_freq);
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.freq_offset,
|
||||
old_ctx->def.chan->freq_offset);
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.chan_width,
|
||||
old_ctx->def.width);
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.center_freq1,
|
||||
old_ctx->def.center_freq1);
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.freq1_offset,
|
||||
old_ctx->def.freq1_offset);
|
||||
SWITCH_ENTRY_ASSIGN(old_chandef.center_freq2,
|
||||
old_ctx->def.center_freq2);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.control_freq,
|
||||
new_ctx->def.chan->center_freq);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.freq_offset,
|
||||
new_ctx->def.chan->freq_offset);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.chan_width,
|
||||
new_ctx->def.width);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.center_freq1,
|
||||
new_ctx->def.center_freq1);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.freq1_offset,
|
||||
new_ctx->def.freq1_offset);
|
||||
SWITCH_ENTRY_ASSIGN(new_chandef.center_freq2,
|
||||
new_ctx->def.center_freq2);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user