Collect the 802.11ax HE capabilities of the Device and register it as part of the wiphy capabilities in the cfg80211 driver. Signed-off-by: Gokul Sivakumar --- drivers/net/wireless/infineon/inffmac/he.c | 112 +++++++++++++++++++++ drivers/net/wireless/infineon/inffmac/he.h | 27 +++++ 2 files changed, 139 insertions(+) create mode 100644 drivers/net/wireless/infineon/inffmac/he.c create mode 100644 drivers/net/wireless/infineon/inffmac/he.h diff --git a/drivers/net/wireless/infineon/inffmac/he.c b/drivers/net/wireless/infineon/inffmac/he.c new file mode 100644 index 000000000000..334c12f5a49c --- /dev/null +++ b/drivers/net/wireless/infineon/inffmac/he.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (c) 2025-2026, Infineon Technologies AG, or an affiliate of Infineon Technologies AG. + * All rights reserved. + */ + +#include +#include "he.h" +#include "dev_cmd.h" +#include "cfg80211.h" +#include "debug.h" + +static struct ieee80211_sband_iftype_data sdata[NUM_NL80211_BANDS]; + +int +inff_he_get_enable(struct inff_if *ifp, u8 *param, int param_len) +{ + s32 ret = 0; + + ret = inff_fwcmd_xtlv_data_get(ifp, "he", INFF_HE_CMD_ENAB, param, param_len); + if (unlikely(ret)) + iphy_err(ifp->drvr, "failed to check if HE is enabled"); + + return ret; +} + +void +inff_he_update_wiphy_cap(struct inff_if *ifp) +{ + struct inff_pub *drvr = ifp->drvr; + struct wiphy *wiphy = drvr->wiphy; + struct ieee80211_supported_band *band; + struct ieee80211_sband_iftype_data *data; + struct ieee80211_sta_he_cap *he_cap; + struct ieee80211_he_cap_elem *he_cap_elem; + struct ieee80211_he_mcs_nss_supp *he_mcs; + u8 mac_cap_info[HE_MAC_CAP_INFO_SIZE] = { 0 }; + u8 phy_cap_info[HE_PHY_CAP_INFO_SIZE] = { 0 }; + u16 capa = 0; + u8 hemode = 0; + int idx = 1, i = 0, j = 0; + + /* HE mode */ + inff_he_get_enable(ifp, &hemode, sizeof(hemode)); + if (!hemode) + return; + + inff_dbg(INFO, "HE Enabled\n"); + + /* HE MAC Capabilities Information */ + if (inff_fwcmd_xtlv_data_get(ifp, "he", INFF_HE_CMD_MACCAP, mac_cap_info, + HE_MAC_CAP_INFO_SIZE)) + iphy_err(drvr, "HE MACCAP error\n"); + + /* HE PHY Capabilities Information */ + if (inff_fwcmd_xtlv_data_get(ifp, "he", INFF_HE_CMD_PHYCAP, phy_cap_info, + HE_PHY_CAP_INFO_SIZE)) + iphy_err(drvr, "HE PHYCAP error\n"); + + /* Update HE Capab for each Band */ + for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) { + band = wiphy->bands[i]; + if (!band) + continue; + + data = &sdata[band->band]; + he_cap = &data->he_cap; + he_cap_elem = &he_cap->he_cap_elem; + he_mcs = &he_cap->he_mcs_nss_supp; + + switch (band->band) { + case NL80211_BAND_6GHZ: + /* HE 6 GHz band capabilities */ + capa = (FIELD_PREP(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START, + IEEE80211_HT_MPDU_DENSITY_8) | + FIELD_PREP(IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP, + IEEE80211_VHT_MAX_AMPDU_1024K) | + FIELD_PREP(IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN, + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454)); + data->he_6ghz_capa.capa = cpu_to_le16(capa); + + /* Band 6GHz supports HE, so */ + fallthrough; + + case NL80211_BAND_5GHZ: + /* Band 5GHz supports HE, so */ + fallthrough; + + case NL80211_BAND_2GHZ: + /* Band 2GHz supports HE */ + data->types_mask = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); + data->he_cap.has_he = true; + + for (j = 0; j < HE_MAC_CAP_INFO_SIZE; j++) + he_cap_elem->mac_cap_info[j] = mac_cap_info[j]; + + for (j = 0; j < HE_PHY_CAP_INFO_SIZE; j++) + he_cap_elem->phy_cap_info[j] = phy_cap_info[j]; + + /* HE Supported MCS and NSS Set */ + he_mcs->rx_mcs_80 = cpu_to_le16(0xfffa); + he_mcs->tx_mcs_80 = cpu_to_le16(0xfffa); + + _ieee80211_set_sband_iftype_data(band, data, idx); + + break; + + default: + break; + } + } +} diff --git a/drivers/net/wireless/infineon/inffmac/he.h b/drivers/net/wireless/infineon/inffmac/he.h new file mode 100644 index 000000000000..643814a1bc42 --- /dev/null +++ b/drivers/net/wireless/infineon/inffmac/he.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: ISC */ +/* + * Copyright (c) 2025-2026, Infineon Technologies AG, or an affiliate of Infineon Technologies AG. + * All rights reserved. + */ + +#ifndef INFF_HE_H +#define INFF_HE_H + +#include "main.h" + +#define HE_MAC_CAP_INFO_SIZE 6 +#define HE_PHY_CAP_INFO_SIZE 11 + +/** + * enum inff_he_cmd - HE iovar subcmds handled by firmware HE module + */ +enum inff_he_cmd { + INFF_HE_CMD_ENAB = 0, + INFF_HE_CMD_MACCAP = 16, + INFF_HE_CMD_PHYCAP = 17, +}; + +int inff_he_get_enable(struct inff_if *ifp, u8 *param, int param_len); +void inff_he_update_wiphy_cap(struct inff_if *ifp); + +#endif /* INFF_HE_H */ -- 2.43.0