wlan-ap-Telecominfraproject/feeds/ipq95xx/mac80211/patches/qca/626-mac80211-add-EHT-support-for-mesh.patch
John Crispin 144c5d00f4 ipq95xx/mac80211: update to ATH12.3-CS
Signed-off-by: John Crispin <john@phrozen.org>
2024-02-28 18:56:21 +01:00

530 lines
18 KiB
Diff

From 369c67787c1106a176582913d1d211be2ac31877 Mon Sep 17 00:00:00 2001
From: Sathishkumar Muruganandam <quic_murugana@quicinc.com>
Date: Tue, 23 Nov 2021 18:19:03 +0530
Subject: [PATCH] mac80211: add EHT support for mesh
Add support for EHT capability, operation information element parsing
and advertisement in mesh beacon, probe responses, and peering action
frames.
Update EHT support configurations based on the parsed elements.
Filter capabilities reported by the firmware based on mesh needs
and remove the capabilities not required for mesh.
Signed-off-by: Sathishkumar Muruganandam <quic_murugana@quicinc.com>
Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com>
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -4009,6 +4009,12 @@ struct ieee80211_multiple_bssid_configur
#define WLAN_OUI_TYPE_MICROSOFT_WPS 4
#define WLAN_OUI_TYPE_MICROSOFT_TPC 8
+#define IEEE80211_EHT_OPER_CTRL_CHANWIDTH_20MHZ 0
+#define IEEE80211_EHT_OPER_CTRL_CHANWIDTH_40MHZ 1
+#define IEEE80211_EHT_OPER_CTRL_CHANWIDTH_80MHZ 2
+#define IEEE80211_EHT_OPER_CTRL_CHANWIDTH_160MHZ 3
+#define IEEE80211_EHT_OPER_CTRL_CHANWIDTH_320MHZ 4
+
/*
* WMM/802.11e Tspec Element
*/
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2411,6 +2411,12 @@ u8 *ieee80211_ie_build_he_cap(ieee80211_
void ieee80211_ie_build_he_6ghz_cap(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
u8 *ieee80211_ie_build_he_oper(u8 *pos, struct cfg80211_chan_def *chandef);
+u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype);
+u8 *ieee80211_ie_build_eht_cap(u8 *pos,
+ const struct ieee80211_sta_he_cap *he_cap,
+ const struct ieee80211_sta_eht_cap *eht_cap,
+ u8 *end);
+u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef);
int ieee80211_parse_bitrates(enum nl80211_chan_width width,
const struct ieee80211_supported_band *sband,
const u8 *srates, int srates_len, u32 *rates);
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -104,7 +104,7 @@ bool mesh_matches_local(struct ieee80211
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, NULL,
+ ieee80211_chandef_he_6ghz_oper(sdata, ie->he_operation, ie->eht_operation,
&sta_chan_def);
if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
@@ -644,6 +644,67 @@ int mesh_add_he_6ghz_cap_ie(struct ieee8
return 0;
}
+int mesh_add_eht_cap_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, u8 ie_len)
+{
+ const struct ieee80211_sta_he_cap *he_cap;
+ const struct ieee80211_sta_eht_cap *eht_cap;
+ struct ieee80211_supported_band *sband;
+ u8 *pos;
+
+ sband = ieee80211_get_sband(sdata);
+ if (!sband)
+ return -EINVAL;
+
+ he_cap = ieee80211_get_he_iftype_cap(sband, NL80211_IFTYPE_MESH_POINT);
+ eht_cap = ieee80211_get_eht_iftype_cap(sband, NL80211_IFTYPE_MESH_POINT);
+
+ if (!he_cap || !eht_cap ||
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
+ return 0;
+
+ if (skb_tailroom(skb) < ie_len)
+ return -ENOMEM;
+
+ pos = skb_put(skb, ie_len);
+ ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, pos + ie_len);
+
+ return 0;
+}
+
+int mesh_add_eht_oper_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb)
+{
+ const struct ieee80211_sta_eht_cap *eht_cap;
+ struct ieee80211_supported_band *sband;
+ u32 len;
+ u8 *pos;
+
+ sband = ieee80211_get_sband(sdata);
+ if (!sband)
+ return -EINVAL;
+
+ eht_cap = ieee80211_get_eht_iftype_cap(sband, NL80211_IFTYPE_MESH_POINT);
+ if (!eht_cap ||
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
+ return 0;
+
+ len = 2 + 1 + sizeof(struct ieee80211_eht_operation) +
+ sizeof(struct ieee80211_eht_operation_info);
+
+ if (skb_tailroom(skb) < len)
+ return -ENOMEM;
+
+ pos = skb_put(skb, len);
+ ieee80211_ie_build_eht_oper(pos, &sdata->vif.bss_conf.chandef);
+
+ return 0;
+}
+
static void ieee80211_mesh_path_timer(struct timer_list *t)
{
struct ieee80211_sub_if_data *sdata =
@@ -681,6 +742,7 @@ ieee80211_mesh_update_bss_params(struct
struct ieee80211_supported_band *sband;
const struct element *cap;
const struct ieee80211_he_operation *he_oper = NULL;
+ const struct ieee80211_eht_operation *eht_oper = NULL;
sband = ieee80211_get_sband(sdata);
if (!sband)
@@ -702,6 +764,18 @@ ieee80211_mesh_update_bss_params(struct
if (he_oper)
sdata->vif.bss_conf.he_oper.params =
__le32_to_cpu(he_oper->he_oper_params);
+
+ if (!ieee80211_get_eht_iftype_cap(sband, NL80211_IFTYPE_MESH_POINT))
+ return;
+
+ sdata->vif.bss_conf.eht_support = true;
+
+ cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_OPERATION, ie, ie_len);
+ if (cap && ieee80211_eht_oper_size_ok(cap, cap->datalen))
+ eht_oper = (void *)(cap->data + 1);
+
+ if (eht_oper)
+ ieee80211_eht_op_ie_to_bss_conf(&sdata->vif, eht_oper);
}
/**
@@ -821,7 +895,7 @@ ieee80211_mesh_build_beacon(struct ieee8
struct ieee80211_chanctx_conf *chanctx_conf;
struct mesh_csa_settings *csa;
enum nl80211_band band;
- u8 ie_len_he_cap;
+ u8 ie_len_he_cap, ie_len_eht_cap;
u8 *pos;
struct ieee80211_sub_if_data *sdata;
int hdr_len = offsetofend(struct ieee80211_mgmt, u.beacon);
@@ -834,6 +908,8 @@ ieee80211_mesh_build_beacon(struct ieee8
ie_len_he_cap = ieee80211_ie_len_he_cap(sdata,
NL80211_IFTYPE_MESH_POINT);
+ ie_len_eht_cap = ieee80211_ie_len_eht_cap(sdata,
+ NL80211_IFTYPE_MESH_POINT);
head_len = hdr_len +
2 + /* NULL SSID */
/* Channel Switch Announcement */
@@ -857,6 +933,9 @@ ieee80211_mesh_build_beacon(struct ieee8
2 + 1 + sizeof(struct ieee80211_he_operation) +
sizeof(struct ieee80211_he_6ghz_oper) +
2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) +
+ ie_len_eht_cap +
+ 2 + 1 + sizeof(struct ieee80211_eht_operation) +
+ + sizeof(struct ieee80211_eht_operation_info) +
ifmsh->ie_len;
bcn = kzalloc(sizeof(*bcn) + head_len + tail_len, GFP_KERNEL);
@@ -978,6 +1057,8 @@ ieee80211_mesh_build_beacon(struct ieee8
mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) ||
mesh_add_he_oper_ie(sdata, skb) ||
mesh_add_he_6ghz_cap_ie(sdata, skb) ||
+ mesh_add_eht_cap_ie(sdata, skb, ie_len_eht_cap) ||
+ mesh_add_eht_oper_ie(sdata, skb) ||
mesh_add_vendor_ies(sdata, skb))
goto out_free;
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -234,6 +234,10 @@ int mesh_add_he_oper_ie(struct ieee80211
struct sk_buff *skb);
int mesh_add_he_6ghz_cap_ie(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
+int mesh_add_eht_cap_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, u8 ie_len);
+int mesh_add_eht_oper_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb);
void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
void ieee80211s_init(void);
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -219,12 +219,14 @@ static int mesh_plink_frame_tx(struct ie
bool include_plid = false;
u16 peering_proto = 0;
u8 *pos, ie_len = 4;
- u8 ie_len_he_cap;
+ u8 ie_len_he_cap, ie_len_eht_cap;
int hdr_len = offsetofend(struct ieee80211_mgmt, u.action.u.self_prot);
int err = -ENOMEM;
ie_len_he_cap = ieee80211_ie_len_he_cap(sdata,
NL80211_IFTYPE_MESH_POINT);
+ ie_len_eht_cap = ieee80211_ie_len_eht_cap(sdata,
+ NL80211_IFTYPE_MESH_POINT);
skb = dev_alloc_skb(local->tx_headroom +
hdr_len +
2 + /* capability info */
@@ -241,6 +243,9 @@ static int mesh_plink_frame_tx(struct ie
2 + 1 + sizeof(struct ieee80211_he_operation) +
sizeof(struct ieee80211_he_6ghz_oper) +
2 + 1 + sizeof(struct ieee80211_he_6ghz_capa) +
+ ie_len_eht_cap +
+ 2 + 1 + sizeof(struct ieee80211_eht_operation) +
+ sizeof(struct ieee80211_eht_operation_info) +
2 + 8 + /* peering IE */
sdata->u.mesh.ie_len);
if (!skb)
@@ -332,7 +337,9 @@ static int mesh_plink_frame_tx(struct ie
mesh_add_vht_oper_ie(sdata, skb) ||
mesh_add_he_cap_ie(sdata, skb, ie_len_he_cap) ||
mesh_add_he_oper_ie(sdata, skb) ||
- mesh_add_he_6ghz_cap_ie(sdata, skb))
+ mesh_add_he_6ghz_cap_ie(sdata, skb) ||
+ mesh_add_eht_cap_ie(sdata, skb, ie_len_eht_cap) ||
+ mesh_add_eht_oper_ie(sdata, skb))
goto free;
}
@@ -457,6 +464,11 @@ static void mesh_sta_info_init(struct ie
elems->he_6ghz_capa,
&sta->deflink);
+ ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband, elems->he_cap,
+ elems->he_cap_len,
+ elems->eht_cap, elems->eht_cap_len,
+ &sta->deflink);
+
if (bw != sta->sta.deflink.bandwidth)
changed |= IEEE80211_RC_BW_CHANGED;
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3141,6 +3141,7 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos,
ht_oper->primary_chan = ieee80211_frequency_to_channel(
chandef->chan->center_freq);
switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_320:
case NL80211_CHAN_WIDTH_160:
case NL80211_CHAN_WIDTH_80P80:
case NL80211_CHAN_WIDTH_80:
@@ -3150,10 +3151,6 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos,
else
ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
break;
- case NL80211_CHAN_WIDTH_320:
- /* HT information element should not be included on 6GHz */
- WARN_ON(1);
- return pos;
default:
ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
break;
@@ -3213,19 +3210,31 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos,
const struct cfg80211_chan_def *chandef)
{
struct ieee80211_vht_operation *vht_oper;
+ struct cfg80211_chan_def tmp_chandef;
+
+ cfg80211_chandef_create(&tmp_chandef, chandef->chan, NL80211_CHAN_NO_HT);
+ tmp_chandef.center_freq1 = chandef->center_freq1;
+ tmp_chandef.center_freq2 = chandef->center_freq2;
+ tmp_chandef.width = chandef->width;
*pos++ = WLAN_EID_VHT_OPERATION;
*pos++ = sizeof(struct ieee80211_vht_operation);
vht_oper = (struct ieee80211_vht_operation *)pos;
vht_oper->center_freq_seg0_idx = ieee80211_frequency_to_channel(
- chandef->center_freq1);
- if (chandef->center_freq2)
+ tmp_chandef.center_freq1);
+ if (tmp_chandef.center_freq2)
vht_oper->center_freq_seg1_idx =
- ieee80211_frequency_to_channel(chandef->center_freq2);
+ ieee80211_frequency_to_channel(tmp_chandef.center_freq2);
else
vht_oper->center_freq_seg1_idx = 0x00;
- switch (chandef->width) {
+ switch (tmp_chandef.width) {
+ case NL80211_CHAN_WIDTH_320:
+ /* Downgrade EHT 320 MHz BW to 160 MHz for VHT & set new center_freq1 */
+ ieee80211_chandef_downgrade(&tmp_chandef);
+ vht_oper->center_freq_seg0_idx =
+ ieee80211_frequency_to_channel(tmp_chandef.center_freq1);
+ fallthrough;
case NL80211_CHAN_WIDTH_160:
/*
* Convert 160 MHz channel width to new style as interop
@@ -3233,7 +3242,7 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos,
*/
vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
vht_oper->center_freq_seg1_idx = vht_oper->center_freq_seg0_idx;
- if (chandef->chan->center_freq < chandef->center_freq1)
+ if (tmp_chandef.chan->center_freq < tmp_chandef.center_freq1)
vht_oper->center_freq_seg0_idx -= 8;
else
vht_oper->center_freq_seg0_idx += 8;
@@ -3248,10 +3257,6 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos,
case NL80211_CHAN_WIDTH_80:
vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
break;
- case NL80211_CHAN_WIDTH_320:
- /* VHT information element should not be included on 6GHz */
- WARN_ON(1);
- return pos;
default:
vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT;
break;
@@ -3269,6 +3274,7 @@ u8 *ieee80211_ie_build_he_oper(u8 *pos,
struct ieee80211_he_6ghz_oper *he_6ghz_op;
u32 he_oper_params;
u8 ie_len = 1 + sizeof(struct ieee80211_he_operation);
+ struct cfg80211_chan_def tmp_chandef;
if (chandef->chan->band == NL80211_BAND_6GHZ)
ie_len += sizeof(struct ieee80211_he_6ghz_oper);
@@ -3298,27 +3304,30 @@ u8 *ieee80211_ie_build_he_oper(u8 *pos,
if (chandef->chan->band != NL80211_BAND_6GHZ)
goto out;
+ cfg80211_chandef_create(&tmp_chandef, chandef->chan, NL80211_CHAN_NO_HT);
+ tmp_chandef.center_freq1 = chandef->center_freq1;
+ tmp_chandef.center_freq2 = chandef->center_freq2;
+ tmp_chandef.width = chandef->width;
/* TODO add VHT operational */
he_6ghz_op = (struct ieee80211_he_6ghz_oper *)pos;
he_6ghz_op->minrate = 6; /* 6 Mbps */
he_6ghz_op->primary =
- ieee80211_frequency_to_channel(chandef->chan->center_freq);
+ ieee80211_frequency_to_channel(tmp_chandef.chan->center_freq);
he_6ghz_op->ccfs0 =
- ieee80211_frequency_to_channel(chandef->center_freq1);
- if (chandef->center_freq2)
+ ieee80211_frequency_to_channel(tmp_chandef.center_freq1);
+ if (tmp_chandef.center_freq2)
he_6ghz_op->ccfs1 =
- ieee80211_frequency_to_channel(chandef->center_freq2);
+ ieee80211_frequency_to_channel(tmp_chandef.center_freq2);
else
he_6ghz_op->ccfs1 = 0;
- switch (chandef->width) {
+ switch (tmp_chandef.width) {
case NL80211_CHAN_WIDTH_320:
- /*
- * TODO: mesh operation is not defined over 6GHz 320 MHz
- * channels.
- */
- WARN_ON(1);
- break;
+ /* Downgrade EHT 320 MHz BW to 160 MHz for HE & set new center_freq1 */
+ ieee80211_chandef_downgrade(&tmp_chandef);
+ he_6ghz_op->ccfs0 =
+ ieee80211_frequency_to_channel(tmp_chandef.center_freq1);
+ fallthrough;
case NL80211_CHAN_WIDTH_160:
/* Convert 160 MHz channel width to new style as interop
* workaround.
@@ -3326,7 +3335,7 @@ u8 *ieee80211_ie_build_he_oper(u8 *pos,
he_6ghz_op->control =
IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ;
he_6ghz_op->ccfs1 = he_6ghz_op->ccfs0;
- if (chandef->chan->center_freq < chandef->center_freq1)
+ if (tmp_chandef.chan->center_freq < tmp_chandef.center_freq1)
he_6ghz_op->ccfs0 -= 8;
else
he_6ghz_op->ccfs0 += 8;
@@ -3355,6 +3364,59 @@ out:
return pos;
}
+u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef)
+{
+ struct ieee80211_eht_operation *eht_oper;
+ struct ieee80211_eht_operation_info *eht_oper_info;
+ u8 ie_len = 1 + sizeof(struct ieee80211_eht_operation) +
+ sizeof(struct ieee80211_eht_operation_info);
+ u8 chwidth = 0;
+
+ *pos++ = WLAN_EID_EXTENSION;
+ *pos++ = ie_len;
+ *pos++ = WLAN_EID_EXT_EHT_OPERATION;
+
+ eht_oper = (struct ieee80211_eht_operation *)pos;
+ pos += sizeof(struct ieee80211_eht_operation);
+
+ eht_oper_info = (struct ieee80211_eht_operation_info *)pos;
+ pos += sizeof(struct ieee80211_eht_operation_info);
+
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_320:
+ chwidth = IEEE80211_EHT_OPER_CTRL_CHANWIDTH_320MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_160:
+ chwidth = IEEE80211_EHT_OPER_CTRL_CHANWIDTH_160MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_80P80:
+ chwidth = IEEE80211_EHT_OPER_CTRL_CHANWIDTH_160MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_80:
+ chwidth = IEEE80211_EHT_OPER_CTRL_CHANWIDTH_80MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_40:
+ chwidth = IEEE80211_EHT_OPER_CTRL_CHANWIDTH_40MHZ;
+ break;
+ default:
+ chwidth = IEEE80211_EHT_OPER_CTRL_CHANWIDTH_20MHZ;
+ break;
+ }
+
+ eht_oper->params |= IEEE80211_EHT_OPER_INFO_PRESENT;
+
+ eht_oper_info->control = chwidth;
+ eht_oper_info->ccfs0 =
+ ieee80211_frequency_to_channel(chandef->center_freq1);
+ eht_oper_info->ccfs1 = 0; /* How to get this? */
+
+ eht_oper->optional[0] = eht_oper_info->control;
+ eht_oper->optional[1] = eht_oper_info->ccfs0;
+ eht_oper->optional[2] = eht_oper_info->ccfs1;
+
+ return pos;
+}
+
bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
struct cfg80211_chan_def *chandef)
{
@@ -4869,7 +4931,7 @@ u8 ieee80211_ie_len_eht_cap(struct ieee8
n = ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
&eht_cap->eht_cap_elem);
return 2 + 1 +
- sizeof(he_cap->he_cap_elem) + n +
+ sizeof(eht_cap->eht_cap_elem) + n +
ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0],
eht_cap->eht_cap_elem.phy_cap_info);
return 0;
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -5803,6 +5803,47 @@ static void ath12k_gen_eht_mcs_nss(struc
sizeof(struct ieee80211_eht_mcs_nss_supp_bw));
}
+static void
+ath12k_mac_filter_eht_cap_mesh(struct ieee80211_eht_cap_elem_fixed *eht_cap_elem)
+{
+ u8 m;
+
+ m = IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS;
+ eht_cap_elem->mac_cap_info[0] &= ~m;
+
+ m = IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO;
+ eht_cap_elem->phy_cap_info[0] &= ~m;
+
+ m = IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
+ IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK |
+ IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK |
+ IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK;
+ eht_cap_elem->phy_cap_info[3] &= ~m;
+
+ m = IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO |
+ IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP |
+ IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP |
+ IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI;
+ eht_cap_elem->phy_cap_info[4] &= ~m;
+
+ m = IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK |
+ IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP |
+ IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP |
+ IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK;
+ eht_cap_elem->phy_cap_info[5] &= ~m;
+
+ m = IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK;
+ eht_cap_elem->phy_cap_info[6] &= ~m;
+
+ m = IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ |
+ IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ |
+ IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ |
+ IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ |
+ IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ |
+ IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ;
+ eht_cap_elem->phy_cap_info[7] &= ~m;
+}
+
static void ath12k_mac_copy_eht_cap(struct ath12k *ar,
struct ath12k_band_cap *band_cap,
struct ieee80211_he_cap_elem *he_cap_elem,
@@ -5837,6 +5878,9 @@ static void ath12k_mac_copy_eht_cap(stru
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ |
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ);
break;
+ case NL80211_IFTYPE_MESH_POINT:
+ ath12k_mac_filter_eht_cap_mesh(eht_cap_elem);
+ break;
default:
break;
}
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -269,6 +269,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(s
case NL80211_CHAN_WIDTH_80:
case NL80211_CHAN_WIDTH_80P80:
case NL80211_CHAN_WIDTH_160:
+ case NL80211_CHAN_WIDTH_320:
bw = ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20;
break;