wifi: mac80211: enable EHT mesh support

Similar to AP beacon, this enables the basic mesh EHT mode, including
EHT operation IE and the fixed field of EHT operation information IE.
As for the optional part (i.e. preamble puncturing bitmap) will be
added in future patch.

Tested-by: Lian Chen <lian.chen@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Link: https://lore.kernel.org/r/1e0ddb9001312451c3e99c4eed2072caf8075f61.1679935259.git.ryder.lee@mediatek.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Ryder Lee
2023-03-28 01:07:42 +08:00
committed by Johannes Berg
parent 0b354b8b09
commit df1875c4f3
5 changed files with 162 additions and 4 deletions

View File

@@ -3485,6 +3485,77 @@ out:
return pos;
}
u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef,
const struct ieee80211_sta_eht_cap *eht_cap)
{
const struct ieee80211_eht_mcs_nss_supp_20mhz_only *eht_mcs_nss =
&eht_cap->eht_mcs_nss_supp.only_20mhz;
struct ieee80211_eht_operation *eht_oper;
struct ieee80211_eht_operation_info *eht_oper_info;
u8 eht_oper_len = offsetof(struct ieee80211_eht_operation, optional);
u8 eht_oper_info_len =
offsetof(struct ieee80211_eht_operation_info, optional);
u8 chan_width = 0;
*pos++ = WLAN_EID_EXTENSION;
*pos++ = 1 + eht_oper_len + eht_oper_info_len;
*pos++ = WLAN_EID_EXT_EHT_OPERATION;
eht_oper = (struct ieee80211_eht_operation *)pos;
memcpy(&eht_oper->basic_mcs_nss, eht_mcs_nss, sizeof(*eht_mcs_nss));
eht_oper->params |= IEEE80211_EHT_OPER_INFO_PRESENT;
pos += eht_oper_len;
eht_oper_info =
(struct ieee80211_eht_operation_info *)eht_oper->optional;
eht_oper_info->ccfs0 =
ieee80211_frequency_to_channel(chandef->center_freq1);
if (chandef->center_freq2)
eht_oper_info->ccfs1 =
ieee80211_frequency_to_channel(chandef->center_freq2);
else
eht_oper_info->ccfs1 = 0;
switch (chandef->width) {
case NL80211_CHAN_WIDTH_320:
chan_width = IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ;
eht_oper_info->ccfs1 = eht_oper_info->ccfs0;
if (chandef->chan->center_freq < chandef->center_freq1)
eht_oper_info->ccfs0 -= 16;
else
eht_oper_info->ccfs0 += 16;
break;
case NL80211_CHAN_WIDTH_160:
eht_oper_info->ccfs1 = eht_oper_info->ccfs0;
if (chandef->chan->center_freq < chandef->center_freq1)
eht_oper_info->ccfs0 -= 8;
else
eht_oper_info->ccfs0 += 8;
fallthrough;
case NL80211_CHAN_WIDTH_80P80:
chan_width = IEEE80211_EHT_OPER_CHAN_WIDTH_160MHZ;
break;
case NL80211_CHAN_WIDTH_80:
chan_width = IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ;
break;
case NL80211_CHAN_WIDTH_40:
chan_width = IEEE80211_EHT_OPER_CHAN_WIDTH_40MHZ;
break;
default:
chan_width = IEEE80211_EHT_OPER_CHAN_WIDTH_20MHZ;
break;
}
eht_oper_info->control = chan_width;
pos += eht_oper_info_len;
/* TODO: eht_oper_info->optional */
return pos;
}
bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
struct cfg80211_chan_def *chandef)
{