Skip to content

Commit

Permalink
wifi: mac80211: clean up HE 6 GHz and EHT chandef parsing
Browse files Browse the repository at this point in the history
In the code we currently check for support 80+80, 160
and 320 channel widths, but really the way this should
be (and is otherwise) handled is that we compute the
highest channel bandwidth given there, and then cut it
down to what we support. This is also needed for wider
bandwidth OFDMA support.

Change the code to remove this limitation and always
parse the highest possible channel width.

Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240129194108.d06f85082e29.I47e68ed3d97b0a2f4ee61e5d8abfcefc8a5b9c08@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Johannes Berg committed Feb 8, 2024
1 parent 310c838 commit 2d9698d
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 93 deletions.
3 changes: 1 addition & 2 deletions net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -2512,9 +2512,8 @@ bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw, u32 vht_cap_info,
const struct ieee80211_ht_operation *htop,
struct cfg80211_chan_def *chandef);
void ieee80211_chandef_eht_oper(const struct ieee80211_eht_operation_info *info,
bool support_160, bool support_320,
struct cfg80211_chan_def *chandef);
bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_local *local,
const struct ieee80211_he_operation *he_oper,
const struct ieee80211_eht_operation *eht_oper,
struct cfg80211_chan_def *chandef);
Expand Down
3 changes: 2 additions & 1 deletion net/mac80211/mesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
ieee80211_chandef_vht_oper(&sdata->local->hw, vht_cap_info,
ie->vht_operation, ie->ht_operation,
&sta_chan_def);
ieee80211_chandef_he_6ghz_oper(sdata, ie->he_operation, ie->eht_operation,
ieee80211_chandef_he_6ghz_oper(sdata->local, ie->he_operation,
ie->eht_operation,
&sta_chan_def);

if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
Expand Down
8 changes: 3 additions & 5 deletions net/mac80211/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ ieee80211_extract_dis_subch_bmap(const struct ieee80211_eht_operation *eht_oper,

/* set 160/320 supported to get the full AP definition */
ieee80211_chandef_eht_oper((const void *)eht_oper->optional,
true, true, &ap_chandef);
&ap_chandef);
ap_center_freq = ap_chandef.center_freq1;
ap_bw = 20 * BIT(u8_get_bits(info->control,
IEEE80211_EHT_OPER_CHAN_WIDTH));
Expand Down Expand Up @@ -280,7 +280,7 @@ ieee80211_determine_ap_chan(struct ieee80211_sub_if_data *sdata,
mode = IEEE80211_CONN_MODE_HE;
}

if (!ieee80211_chandef_he_6ghz_oper(sdata, he_oper,
if (!ieee80211_chandef_he_6ghz_oper(sdata->local, he_oper,
eht_oper, chandef)) {
sdata_info(sdata, "bad HE/EHT 6 GHz operation\n");
return IEEE80211_CONN_MODE_LEGACY;
Expand Down Expand Up @@ -394,9 +394,7 @@ ieee80211_determine_ap_chan(struct ieee80211_sub_if_data *sdata,
struct cfg80211_chan_def eht_chandef = *chandef;

ieee80211_chandef_eht_oper((const void *)eht_oper->optional,
eht_chandef.width ==
NL80211_CHAN_WIDTH_160,
false, &eht_chandef);
&eht_chandef);

if (!cfg80211_chandef_valid(&eht_chandef)) {
sdata_info(sdata,
Expand Down
4 changes: 1 addition & 3 deletions net/mac80211/spectmgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,7 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
/* start with the CSA one */
new_vht_chandef = csa_ie->chandef;
/* and update the width accordingly */
/* FIXME: support 160/320 */
ieee80211_chandef_eht_oper(&bwi->info, true, true,
&new_vht_chandef);
ieee80211_chandef_eht_oper(&bwi->info, &new_vht_chandef);
} else if (wide_bw_chansw_ie) {
u8 new_seg1 = wide_bw_chansw_ie->new_center_freq_seg1;
struct ieee80211_vht_operation vht_oper = {
Expand Down
104 changes: 22 additions & 82 deletions net/mac80211/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -3841,7 +3841,6 @@ bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw, u32 vht_cap_info,
}

void ieee80211_chandef_eht_oper(const struct ieee80211_eht_operation_info *info,
bool support_160, bool support_320,
struct cfg80211_chan_def *chandef)
{
chandef->center_freq1 =
Expand All @@ -3860,80 +3859,34 @@ void ieee80211_chandef_eht_oper(const struct ieee80211_eht_operation_info *info,
chandef->width = NL80211_CHAN_WIDTH_80;
break;
case IEEE80211_EHT_OPER_CHAN_WIDTH_160MHZ:
if (support_160) {
chandef->width = NL80211_CHAN_WIDTH_160;
chandef->center_freq1 =
ieee80211_channel_to_frequency(info->ccfs1,
chandef->chan->band);
} else {
chandef->width = NL80211_CHAN_WIDTH_80;
}
chandef->width = NL80211_CHAN_WIDTH_160;
chandef->center_freq1 =
ieee80211_channel_to_frequency(info->ccfs1,
chandef->chan->band);
break;
case IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ:
if (support_320) {
chandef->width = NL80211_CHAN_WIDTH_320;
chandef->center_freq1 =
ieee80211_channel_to_frequency(info->ccfs1,
chandef->chan->band);
} else if (support_160) {
chandef->width = NL80211_CHAN_WIDTH_160;
} else {
chandef->width = NL80211_CHAN_WIDTH_80;

if (chandef->center_freq1 > chandef->chan->center_freq)
chandef->center_freq1 -= 40;
else
chandef->center_freq1 += 40;
}
chandef->width = NL80211_CHAN_WIDTH_320;
chandef->center_freq1 =
ieee80211_channel_to_frequency(info->ccfs1,
chandef->chan->band);
break;
}
}

bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_local *local,
const struct ieee80211_he_operation *he_oper,
const struct ieee80211_eht_operation *eht_oper,
struct cfg80211_chan_def *chandef)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
enum nl80211_iftype iftype = ieee80211_vif_type_p2p(&sdata->vif);
const struct ieee80211_sta_he_cap *he_cap;
const struct ieee80211_sta_eht_cap *eht_cap;
struct cfg80211_chan_def he_chandef = *chandef;
const struct ieee80211_he_6ghz_oper *he_6ghz_oper;
bool support_80_80, support_160, support_320;
u8 he_phy_cap, eht_phy_cap;
u32 freq;

if (chandef->chan->band != NL80211_BAND_6GHZ)
return true;

sband = local->hw.wiphy->bands[NL80211_BAND_6GHZ];

he_cap = ieee80211_get_he_iftype_cap(sband, iftype);
if (!he_cap) {
sdata_info(sdata, "Missing iftype sband data/HE cap");
return false;
}

he_phy_cap = he_cap->he_cap_elem.phy_cap_info[0];
support_160 =
he_phy_cap &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
support_80_80 =
he_phy_cap &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;

if (!he_oper) {
sdata_info(sdata,
"HE is not advertised on (on %d MHz), expect issues\n",
chandef->chan->center_freq);
if (!he_oper)
return false;
}

eht_cap = ieee80211_get_eht_iftype_cap(sband, iftype);
if (!eht_cap)
eht_oper = NULL;

he_6ghz_oper = ieee80211_he_6ghz_oper(he_oper);
if (!he_6ghz_oper)
Expand All @@ -3946,7 +3899,10 @@ bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
*/
freq = ieee80211_channel_to_frequency(he_6ghz_oper->primary,
NL80211_BAND_6GHZ);
he_chandef.chan = ieee80211_get_channel(sdata->local->hw.wiphy, freq);
he_chandef.chan = ieee80211_get_channel(local->hw.wiphy, freq);

if (!he_chandef.chan)
return false;

if (!eht_oper ||
!(eht_oper->params & IEEE80211_EHT_OPER_INFO_PRESENT)) {
Expand All @@ -3965,13 +3921,10 @@ bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
he_chandef.width = NL80211_CHAN_WIDTH_80;
if (!he_6ghz_oper->ccfs1)
break;
if (abs(he_6ghz_oper->ccfs1 - he_6ghz_oper->ccfs0) == 8) {
if (support_160)
he_chandef.width = NL80211_CHAN_WIDTH_160;
} else {
if (support_80_80)
he_chandef.width = NL80211_CHAN_WIDTH_80P80;
}
if (abs(he_6ghz_oper->ccfs1 - he_6ghz_oper->ccfs0) == 8)
he_chandef.width = NL80211_CHAN_WIDTH_160;
else
he_chandef.width = NL80211_CHAN_WIDTH_80P80;
break;
}

Expand All @@ -3983,30 +3936,17 @@ bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
he_chandef.center_freq1 =
ieee80211_channel_to_frequency(he_6ghz_oper->ccfs0,
NL80211_BAND_6GHZ);
if (support_80_80 || support_160)
he_chandef.center_freq2 =
ieee80211_channel_to_frequency(he_6ghz_oper->ccfs1,
NL80211_BAND_6GHZ);
he_chandef.center_freq2 =
ieee80211_channel_to_frequency(he_6ghz_oper->ccfs1,
NL80211_BAND_6GHZ);
}
} else {
eht_phy_cap = eht_cap->eht_cap_elem.phy_cap_info[0];
support_320 =
eht_phy_cap & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;

ieee80211_chandef_eht_oper((const void *)eht_oper->optional,
support_160, support_320,
&he_chandef);
}

if (!cfg80211_chandef_valid(&he_chandef)) {
sdata_info(sdata,
"HE 6GHz operation resulted in invalid chandef: %d MHz/%d/%d MHz/%d MHz\n",
he_chandef.chan ? he_chandef.chan->center_freq : 0,
he_chandef.width,
he_chandef.center_freq1,
he_chandef.center_freq2);
if (!cfg80211_chandef_valid(&he_chandef))
return false;
}

*chandef = he_chandef;

Expand Down

0 comments on commit 2d9698d

Please sign in to comment.