mac80211: Use a cfg80211_chan_def in ieee80211_hw_conf_chan
Drivers that don't use chanctxes cannot perform VHT association because they still use a "backward compatibility" pair of {ieee80211_channel, nl80211_channel_type} in ieee80211_conf and ieee80211_local. Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com> [fix kernel-doc] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:

committed by
Johannes Berg

parent
219c38674c
commit
675a0b049a
@@ -805,8 +805,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
|
||||
IEEE80211_CHANCTX_EXCLUSIVE);
|
||||
}
|
||||
} else if (local->open_count == local->monitors) {
|
||||
local->_oper_channel = chandef->chan;
|
||||
local->_oper_channel_type = cfg80211_get_chandef_type(chandef);
|
||||
local->_oper_chandef = *chandef;
|
||||
ieee80211_hw_config(local, 0);
|
||||
}
|
||||
|
||||
@@ -3373,9 +3372,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
|
||||
if (local->use_chanctx)
|
||||
*chandef = local->monitor_chandef;
|
||||
else
|
||||
cfg80211_chandef_create(chandef,
|
||||
local->_oper_channel,
|
||||
local->_oper_channel_type);
|
||||
*chandef = local->_oper_chandef;
|
||||
ret = 0;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
@@ -22,7 +22,7 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local,
|
||||
drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
|
||||
|
||||
if (!local->use_chanctx) {
|
||||
local->_oper_channel_type = cfg80211_get_chandef_type(chandef);
|
||||
local->_oper_chandef = *chandef;
|
||||
ieee80211_hw_config(local, 0);
|
||||
}
|
||||
}
|
||||
@@ -77,9 +77,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
|
||||
ctx->mode = mode;
|
||||
|
||||
if (!local->use_chanctx) {
|
||||
local->_oper_channel_type =
|
||||
cfg80211_get_chandef_type(chandef);
|
||||
local->_oper_channel = chandef->chan;
|
||||
local->_oper_chandef = *chandef;
|
||||
ieee80211_hw_config(local, 0);
|
||||
} else {
|
||||
err = drv_add_chanctx(local, ctx);
|
||||
@@ -106,7 +104,10 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
|
||||
WARN_ON_ONCE(ctx->refcount != 0);
|
||||
|
||||
if (!local->use_chanctx) {
|
||||
local->_oper_channel_type = NL80211_CHAN_NO_HT;
|
||||
struct cfg80211_chan_def *chandef = &local->_oper_chandef;
|
||||
chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||
chandef->center_freq1 = chandef->chan->center_freq;
|
||||
chandef->center_freq2 = 0;
|
||||
ieee80211_hw_config(local, 0);
|
||||
} else {
|
||||
drv_remove_chanctx(local, ctx);
|
||||
|
@@ -1021,8 +1021,7 @@ struct ieee80211_local {
|
||||
struct ieee80211_sub_if_data __rcu *scan_sdata;
|
||||
struct ieee80211_channel *csa_channel;
|
||||
/* For backward compatibility only -- do not use */
|
||||
struct ieee80211_channel *_oper_channel;
|
||||
enum nl80211_channel_type _oper_channel_type;
|
||||
struct cfg80211_chan_def _oper_chandef;
|
||||
|
||||
/* Temporary remain-on-channel for off-channel operations */
|
||||
struct ieee80211_channel *tmp_channel;
|
||||
|
@@ -95,42 +95,47 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
|
||||
static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_channel *chan;
|
||||
struct cfg80211_chan_def chandef = {};
|
||||
u32 changed = 0;
|
||||
int power;
|
||||
enum nl80211_channel_type channel_type;
|
||||
u32 offchannel_flag;
|
||||
|
||||
offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
|
||||
|
||||
if (local->scan_channel) {
|
||||
chan = local->scan_channel;
|
||||
chandef.chan = local->scan_channel;
|
||||
/* If scanning on oper channel, use whatever channel-type
|
||||
* is currently in use.
|
||||
*/
|
||||
if (chan == local->_oper_channel)
|
||||
channel_type = local->_oper_channel_type;
|
||||
else
|
||||
channel_type = NL80211_CHAN_NO_HT;
|
||||
if (chandef.chan == local->_oper_chandef.chan) {
|
||||
chandef = local->_oper_chandef;
|
||||
} else {
|
||||
chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||
chandef.center_freq1 = chandef.chan->center_freq;
|
||||
}
|
||||
} else if (local->tmp_channel) {
|
||||
chan = local->tmp_channel;
|
||||
channel_type = NL80211_CHAN_NO_HT;
|
||||
} else {
|
||||
chan = local->_oper_channel;
|
||||
channel_type = local->_oper_channel_type;
|
||||
}
|
||||
chandef.chan = local->tmp_channel;
|
||||
chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||
chandef.center_freq1 = chandef.chan->center_freq;
|
||||
} else
|
||||
chandef = local->_oper_chandef;
|
||||
|
||||
if (chan != local->_oper_channel ||
|
||||
channel_type != local->_oper_channel_type)
|
||||
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);
|
||||
|
||||
if (!cfg80211_chandef_identical(&chandef, &local->_oper_chandef))
|
||||
local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
|
||||
else
|
||||
local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
|
||||
|
||||
offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
|
||||
|
||||
if (offchannel_flag || chan != local->hw.conf.channel ||
|
||||
channel_type != local->hw.conf.channel_type) {
|
||||
local->hw.conf.channel = chan;
|
||||
local->hw.conf.channel_type = channel_type;
|
||||
if (offchannel_flag ||
|
||||
!cfg80211_chandef_identical(&local->hw.conf.chandef,
|
||||
&local->_oper_chandef)) {
|
||||
local->hw.conf.chandef = chandef;
|
||||
changed |= IEEE80211_CONF_CHANGE_CHANNEL;
|
||||
}
|
||||
|
||||
@@ -146,7 +151,7 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
|
||||
changed |= IEEE80211_CONF_CHANGE_SMPS;
|
||||
}
|
||||
|
||||
power = chan->max_power;
|
||||
power = chandef.chan->max_power;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||
@@ -740,11 +745,15 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
sband = local->hw.wiphy->bands[band];
|
||||
if (!sband)
|
||||
continue;
|
||||
if (!local->use_chanctx && !local->_oper_channel) {
|
||||
if (!local->use_chanctx && !local->_oper_chandef.chan) {
|
||||
/* init channel we're on */
|
||||
local->hw.conf.channel =
|
||||
local->_oper_channel = &sband->channels[0];
|
||||
local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
|
||||
struct cfg80211_chan_def chandef = {
|
||||
.chan = &sband->channels[0],
|
||||
.width = NL80211_CHAN_NO_HT,
|
||||
.center_freq1 = sband->channels[0].center_freq,
|
||||
.center_freq2 = 0
|
||||
};
|
||||
local->hw.conf.chandef = local->_oper_chandef = chandef;
|
||||
}
|
||||
cfg80211_chandef_create(&local->monitor_chandef,
|
||||
&sband->channels[0],
|
||||
|
@@ -988,6 +988,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata =
|
||||
container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
@@ -997,21 +998,30 @@ static void ieee80211_chswitch_work(struct work_struct *work)
|
||||
if (!ifmgd->associated)
|
||||
goto out;
|
||||
|
||||
sdata->local->_oper_channel = sdata->local->csa_channel;
|
||||
if (!sdata->local->ops->channel_switch) {
|
||||
/*
|
||||
* FIXME: Here we are downgrading to NL80211_CHAN_WIDTH_20_NOHT
|
||||
* and don't adjust our ht/vht settings
|
||||
* This is wrong - we should behave according to the CSA params
|
||||
*/
|
||||
local->_oper_chandef.chan = local->csa_channel;
|
||||
local->_oper_chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
|
||||
local->_oper_chandef.center_freq1 =
|
||||
local->_oper_chandef.chan->center_freq;
|
||||
local->_oper_chandef.center_freq2 = 0;
|
||||
|
||||
if (!local->ops->channel_switch) {
|
||||
/* call "hw_config" only if doing sw channel switch */
|
||||
ieee80211_hw_config(sdata->local,
|
||||
IEEE80211_CONF_CHANGE_CHANNEL);
|
||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
|
||||
} else {
|
||||
/* update the device channel directly */
|
||||
sdata->local->hw.conf.channel = sdata->local->_oper_channel;
|
||||
local->hw.conf.chandef = local->_oper_chandef;
|
||||
}
|
||||
|
||||
/* XXX: shouldn't really modify cfg80211-owned data! */
|
||||
ifmgd->associated->channel = sdata->local->_oper_channel;
|
||||
ifmgd->associated->channel = local->_oper_chandef.chan;
|
||||
|
||||
/* XXX: wait for a beacon first? */
|
||||
ieee80211_wake_queues_by_reason(&sdata->local->hw,
|
||||
ieee80211_wake_queues_by_reason(&local->hw,
|
||||
IEEE80211_MAX_QUEUE_MAP,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
out:
|
||||
|
@@ -384,7 +384,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
|
||||
{
|
||||
int i;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
enum ieee80211_band band = local->hw.conf.channel->band;
|
||||
enum ieee80211_band band = local->hw.conf.chandef.chan->band;
|
||||
u32 tx_flags;
|
||||
|
||||
tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
|
||||
@@ -401,7 +401,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
|
||||
local->scan_req->ssids[i].ssid_len,
|
||||
local->scan_req->ie, local->scan_req->ie_len,
|
||||
local->scan_req->rates[band], false,
|
||||
tx_flags, local->hw.conf.channel, true);
|
||||
tx_flags, local->hw.conf.chandef.chan, true);
|
||||
|
||||
/*
|
||||
* After sending probe requests, wait for probe responses
|
||||
@@ -467,7 +467,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
|
||||
if (local->ops->hw_scan) {
|
||||
__set_bit(SCAN_HW_SCANNING, &local->scanning);
|
||||
} else if ((req->n_channels == 1) &&
|
||||
(req->channels[0] == local->_oper_channel)) {
|
||||
(req->channels[0] == local->_oper_chandef.chan)) {
|
||||
/*
|
||||
* If we are scanning only on the operating channel
|
||||
* then we do not need to stop normal activities
|
||||
|
@@ -28,27 +28,27 @@
|
||||
#define VIF_PR_FMT " vif:%s(%d%s)"
|
||||
#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
|
||||
|
||||
#define CHANDEF_ENTRY __field(u32, control_freq) \
|
||||
__field(u32, chan_width) \
|
||||
__field(u32, center_freq1) \
|
||||
#define CHANDEF_ENTRY __field(u32, control_freq) \
|
||||
__field(u32, chan_width) \
|
||||
__field(u32, center_freq1) \
|
||||
__field(u32, center_freq2)
|
||||
#define CHANDEF_ASSIGN(c) \
|
||||
__entry->control_freq = (c)->chan->center_freq; \
|
||||
__entry->chan_width = (c)->width; \
|
||||
__entry->center_freq1 = (c)->center_freq1; \
|
||||
#define CHANDEF_ASSIGN(c) \
|
||||
__entry->control_freq = (c)->chan ? (c)->chan->center_freq : 0; \
|
||||
__entry->chan_width = (c)->width; \
|
||||
__entry->center_freq1 = (c)->center_freq1; \
|
||||
__entry->center_freq2 = (c)->center_freq2;
|
||||
#define CHANDEF_PR_FMT " control:%d MHz width:%d center: %d/%d MHz"
|
||||
#define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \
|
||||
#define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \
|
||||
__entry->center_freq1, __entry->center_freq2
|
||||
|
||||
#define CHANCTX_ENTRY CHANDEF_ENTRY \
|
||||
__field(u8, rx_chains_static) \
|
||||
#define CHANCTX_ENTRY CHANDEF_ENTRY \
|
||||
__field(u8, rx_chains_static) \
|
||||
__field(u8, rx_chains_dynamic)
|
||||
#define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def) \
|
||||
__entry->rx_chains_static = ctx->conf.rx_chains_static; \
|
||||
#define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def) \
|
||||
__entry->rx_chains_static = ctx->conf.rx_chains_static; \
|
||||
__entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic
|
||||
#define CHANCTX_PR_FMT CHANDEF_PR_FMT " chains:%d/%d"
|
||||
#define CHANCTX_PR_ARG CHANDEF_PR_ARG, \
|
||||
#define CHANCTX_PR_ARG CHANDEF_PR_ARG, \
|
||||
__entry->rx_chains_static, __entry->rx_chains_dynamic
|
||||
|
||||
|
||||
@@ -286,8 +286,7 @@ TRACE_EVENT(drv_config,
|
||||
__field(u16, listen_interval)
|
||||
__field(u8, long_frame_max_tx_count)
|
||||
__field(u8, short_frame_max_tx_count)
|
||||
__field(int, center_freq)
|
||||
__field(int, channel_type)
|
||||
CHANDEF_ENTRY
|
||||
__field(int, smps)
|
||||
),
|
||||
|
||||
@@ -303,15 +302,13 @@ TRACE_EVENT(drv_config,
|
||||
local->hw.conf.long_frame_max_tx_count;
|
||||
__entry->short_frame_max_tx_count =
|
||||
local->hw.conf.short_frame_max_tx_count;
|
||||
__entry->center_freq = local->hw.conf.channel ?
|
||||
local->hw.conf.channel->center_freq : 0;
|
||||
__entry->channel_type = local->hw.conf.channel_type;
|
||||
CHANDEF_ASSIGN(&local->hw.conf.chandef)
|
||||
__entry->smps = local->hw.conf.smps_mode;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
LOCAL_PR_FMT " ch:%#x freq:%d",
|
||||
LOCAL_PR_ARG, __entry->changed, __entry->center_freq
|
||||
LOCAL_PR_FMT " ch:%#x" CHANDEF_PR_FMT,
|
||||
LOCAL_PR_ARG, __entry->changed, CHANDEF_PR_ARG
|
||||
)
|
||||
);
|
||||
|
||||
|
@@ -1709,7 +1709,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
|
||||
if (chanctx_conf)
|
||||
chan = chanctx_conf->def.chan;
|
||||
else if (!local->use_chanctx)
|
||||
chan = local->_oper_channel;
|
||||
chan = local->_oper_chandef.chan;
|
||||
else
|
||||
goto fail_rcu;
|
||||
|
||||
@@ -1843,7 +1843,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||
* This is the exception! WDS style interfaces are prohibited
|
||||
* when channel contexts are in used so this must be valid
|
||||
*/
|
||||
band = local->hw.conf.channel->band;
|
||||
band = local->hw.conf.chandef.chan->band;
|
||||
break;
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
|
@@ -2171,8 +2171,7 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work)
|
||||
/* currently not handled */
|
||||
WARN_ON(1);
|
||||
else {
|
||||
cfg80211_chandef_create(&chandef, local->hw.conf.channel,
|
||||
local->hw.conf.channel_type);
|
||||
chandef = local->hw.conf.chandef;
|
||||
cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user