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:
Karl Beldan
2013-03-25 16:26:57 +01:00
committed by Johannes Berg
parent 219c38674c
commit 675a0b049a
70 changed files with 292 additions and 243 deletions

View File

@@ -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();

View File

@@ -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);

View File

@@ -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;

View File

@@ -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],

View File

@@ -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:

View File

@@ -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

View File

@@ -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
)
);

View File

@@ -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:

View File

@@ -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);
}
}