Commit 8ac3c704 authored by Johannes Berg's avatar Johannes Berg

mac80211: refactor HT/VHT to chandef code

The station MLME and IBSS/mesh ones use entirely different
code for interpreting HT and VHT operation elements. Change
the code that interprets them a bit - it now modifies an
existing chandef - and use it also in the MLME code.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent de3bb771
...@@ -1050,9 +1050,8 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata, ...@@ -1050,9 +1050,8 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
enum ieee80211_sta_rx_bandwidth bw = sta->sta.bandwidth; enum ieee80211_sta_rx_bandwidth bw = sta->sta.bandwidth;
ieee80211_ht_oper_to_chandef(channel, cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
elems->ht_operation, ieee80211_chandef_ht_oper(elems->ht_operation, &chandef);
&chandef);
memcpy(&htcap_ie, elems->ht_cap_elem, sizeof(htcap_ie)); memcpy(&htcap_ie, elems->ht_cap_elem, sizeof(htcap_ie));
rates_updated |= ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, rates_updated |= ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
...@@ -1066,9 +1065,8 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata, ...@@ -1066,9 +1065,8 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
struct ieee80211_vht_cap cap_ie; struct ieee80211_vht_cap cap_ie;
struct ieee80211_sta_vht_cap cap = sta->sta.vht_cap; struct ieee80211_sta_vht_cap cap = sta->sta.vht_cap;
ieee80211_vht_oper_to_chandef(channel, ieee80211_chandef_vht_oper(elems->vht_operation,
elems->vht_operation, &chandef);
&chandef);
memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie)); memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie));
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
&cap_ie, sta); &cap_ie, sta);
......
...@@ -1988,12 +1988,10 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, ...@@ -1988,12 +1988,10 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo); u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo);
/* channel management */ /* channel management */
void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
const struct ieee80211_ht_operation *ht_oper, struct cfg80211_chan_def *chandef);
struct cfg80211_chan_def *chandef); bool ieee80211_chandef_vht_oper(const struct ieee80211_vht_operation *oper,
void ieee80211_vht_oper_to_chandef(struct ieee80211_channel *control_chan, struct cfg80211_chan_def *chandef);
const struct ieee80211_vht_operation *oper,
struct cfg80211_chan_def *chandef);
u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c); u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c);
int __must_check int __must_check
......
...@@ -91,11 +91,10 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, ...@@ -91,11 +91,10 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
if (sdata->vif.bss_conf.basic_rates != basic_rates) if (sdata->vif.bss_conf.basic_rates != basic_rates)
return false; return false;
ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, cfg80211_chandef_create(&sta_chan_def, sdata->vif.bss_conf.chandef.chan,
ie->ht_operation, &sta_chan_def); NL80211_CHAN_NO_HT);
ieee80211_chandef_ht_oper(ie->ht_operation, &sta_chan_def);
ieee80211_vht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, ieee80211_chandef_vht_oper(ie->vht_operation, &sta_chan_def);
ie->vht_operation, &sta_chan_def);
if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
&sta_chan_def)) &sta_chan_def))
......
...@@ -196,16 +196,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ...@@ -196,16 +196,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
/* check 40 MHz support, if we have it */ /* check 40 MHz support, if we have it */
if (sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { if (sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { ieee80211_chandef_ht_oper(ht_oper, chandef);
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
chandef->width = NL80211_CHAN_WIDTH_40;
chandef->center_freq1 += 10;
break;
case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
chandef->width = NL80211_CHAN_WIDTH_40;
chandef->center_freq1 -= 10;
break;
}
} else { } else {
/* 40 MHz (and 80 MHz) must be supported for VHT */ /* 40 MHz (and 80 MHz) must be supported for VHT */
ret = IEEE80211_STA_DISABLE_VHT; ret = IEEE80211_STA_DISABLE_VHT;
...@@ -219,35 +210,11 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ...@@ -219,35 +210,11 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
goto out; goto out;
} }
vht_chandef.chan = channel; vht_chandef = *chandef;
vht_chandef.center_freq1 = if (!ieee80211_chandef_vht_oper(vht_oper, &vht_chandef)) {
ieee80211_channel_to_frequency(vht_oper->center_freq_seg1_idx,
channel->band);
vht_chandef.center_freq2 = 0;
switch (vht_oper->chan_width) {
case IEEE80211_VHT_CHANWIDTH_USE_HT:
vht_chandef.width = chandef->width;
vht_chandef.center_freq1 = chandef->center_freq1;
break;
case IEEE80211_VHT_CHANWIDTH_80MHZ:
vht_chandef.width = NL80211_CHAN_WIDTH_80;
break;
case IEEE80211_VHT_CHANWIDTH_160MHZ:
vht_chandef.width = NL80211_CHAN_WIDTH_160;
break;
case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
vht_chandef.width = NL80211_CHAN_WIDTH_80P80;
vht_chandef.center_freq2 =
ieee80211_channel_to_frequency(
vht_oper->center_freq_seg2_idx,
channel->band);
break;
default:
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
sdata_info(sdata, sdata_info(sdata,
"AP VHT operation IE has invalid channel width (%d), disable VHT\n", "AP VHT information is invalid, disable VHT\n");
vht_oper->chan_width);
ret = IEEE80211_STA_DISABLE_VHT; ret = IEEE80211_STA_DISABLE_VHT;
goto out; goto out;
} }
......
...@@ -2383,17 +2383,13 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, ...@@ -2383,17 +2383,13 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
return pos + sizeof(struct ieee80211_vht_operation); return pos + sizeof(struct ieee80211_vht_operation);
} }
void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
const struct ieee80211_ht_operation *ht_oper, struct cfg80211_chan_def *chandef)
struct cfg80211_chan_def *chandef)
{ {
enum nl80211_channel_type channel_type; enum nl80211_channel_type channel_type;
if (!ht_oper) { if (!ht_oper)
cfg80211_chandef_create(chandef, control_chan, return false;
NL80211_CHAN_NO_HT);
return;
}
switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
case IEEE80211_HT_PARAM_CHA_SEC_NONE: case IEEE80211_HT_PARAM_CHA_SEC_NONE:
...@@ -2407,42 +2403,52 @@ void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, ...@@ -2407,42 +2403,52 @@ void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
break; break;
default: default:
channel_type = NL80211_CHAN_NO_HT; channel_type = NL80211_CHAN_NO_HT;
return false;
} }
cfg80211_chandef_create(chandef, control_chan, channel_type); cfg80211_chandef_create(chandef, chandef->chan, channel_type);
return true;
} }
void ieee80211_vht_oper_to_chandef(struct ieee80211_channel *control_chan, bool ieee80211_chandef_vht_oper(const struct ieee80211_vht_operation *oper,
const struct ieee80211_vht_operation *oper, struct cfg80211_chan_def *chandef)
struct cfg80211_chan_def *chandef)
{ {
struct cfg80211_chan_def new = *chandef;
int cf1, cf2;
if (!oper) if (!oper)
return; return false;
chandef->chan = control_chan; cf1 = ieee80211_channel_to_frequency(oper->center_freq_seg1_idx,
chandef->chan->band);
cf2 = ieee80211_channel_to_frequency(oper->center_freq_seg2_idx,
chandef->chan->band);
switch (oper->chan_width) { switch (oper->chan_width) {
case IEEE80211_VHT_CHANWIDTH_USE_HT: case IEEE80211_VHT_CHANWIDTH_USE_HT:
break; break;
case IEEE80211_VHT_CHANWIDTH_80MHZ: case IEEE80211_VHT_CHANWIDTH_80MHZ:
chandef->width = NL80211_CHAN_WIDTH_80; new.width = NL80211_CHAN_WIDTH_80;
new.center_freq1 = cf1;
break; break;
case IEEE80211_VHT_CHANWIDTH_160MHZ: case IEEE80211_VHT_CHANWIDTH_160MHZ:
chandef->width = NL80211_CHAN_WIDTH_160; new.width = NL80211_CHAN_WIDTH_160;
new.center_freq1 = cf1;
break; break;
case IEEE80211_VHT_CHANWIDTH_80P80MHZ: case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
chandef->width = NL80211_CHAN_WIDTH_80P80; new.width = NL80211_CHAN_WIDTH_80P80;
new.center_freq1 = cf1;
new.center_freq2 = cf2;
break; break;
default: default:
break; return false;
} }
chandef->center_freq1 = if (!cfg80211_chandef_valid(&new))
ieee80211_channel_to_frequency(oper->center_freq_seg1_idx, return false;
control_chan->band);
chandef->center_freq2 = *chandef = new;
ieee80211_channel_to_frequency(oper->center_freq_seg2_idx, return true;
control_chan->band);
} }
int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment