From patchwork Wed Dec 22 09:04:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Veerendranath Jakkam X-Patchwork-Id: 12691301 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 51323C433EF for ; Wed, 22 Dec 2021 09:05:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236873AbhLVJFl (ORCPT ); Wed, 22 Dec 2021 04:05:41 -0500 Received: from alexa-out-sd-02.qualcomm.com ([199.106.114.39]:34949 "EHLO alexa-out-sd-02.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232940AbhLVJFl (ORCPT ); Wed, 22 Dec 2021 04:05:41 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1640163941; x=1671699941; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=6Ac0fZOO9O4g/H/0IDOlMuzuRMio8rh8lqeE+uCSvBk=; b=dlhPcI+NrvGer+HE+uBrkYKL+I7pI99DeBqhFodndIwsyBFGPblRMzw2 ua8kor+O/YTn49DXAfdU5/CVAflG9aX2kuReUaVZ3IBMwE0KwdGCGz+2V gIzZpQhBD4td68znXM6XL2+NAMhf7mH+fGG5witDZV1qbquWH/ZO3nTDe U=; Received: from unknown (HELO ironmsg05-sd.qualcomm.com) ([10.53.140.145]) by alexa-out-sd-02.qualcomm.com with ESMTP; 22 Dec 2021 01:05:40 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.47.97.222]) by ironmsg05-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Dec 2021 01:05:40 -0800 Received: from nalasex01a.na.qualcomm.com (10.47.209.196) by nasanex01c.na.qualcomm.com (10.47.97.222) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Wed, 22 Dec 2021 01:05:40 -0800 Received: from hu-vjakkam-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Wed, 22 Dec 2021 01:05:36 -0800 From: Veerendranath Jakkam To: CC: , , , , , , Subject: [PATCH 1/6] ieee80211: add EHT capabilities element definitions Date: Wed, 22 Dec 2021 14:34:38 +0530 Message-ID: <1640163883-12696-2-git-send-email-quic_vjakkam@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640163883-12696-1-git-send-email-quic_vjakkam@quicinc.com> References: <1640163883-12696-1-git-send-email-quic_vjakkam@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Vikram Kandukuri Add definitions from P802.11be_D1.3, Section 9.4.2.313 EHT Capabilities element and related helper functions. Signed-off-by: Vikram Kandukuri Co-authored-by: Aloka Dixit Signed-off-by: Aloka Dixit Co-authored-by: Veerendranath Jakkam Signed-off-by: Veerendranath Jakkam --- include/linux/ieee80211.h | 702 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 702 insertions(+) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 559b6c6..5137e7d 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -20,6 +20,7 @@ #include #include #include +#include /* * DS bit usage @@ -2606,6 +2607,706 @@ ieee80211_he_spr_size(const u8 *he_spr_ie) #define IEEE80211_MAX_USF FIELD_MAX(LISTEN_INT_USF) #define IEEE80211_MAX_UI FIELD_MAX(LISTEN_INT_UI) +/** + * struct ieee80211_eht_cap_elem - EHT capabilities element + * + * @mac_cap_info: EHT MAC Capabilities Information + * @phy_cap_info: EHT PHY Capabilities Information + * + * This structure represents the "EHT capabilities element" fixed fields as + * described in P802.11be_D1.3 section 9.4.2.313.2 and 9.4.2.313.3. + */ +struct ieee80211_eht_cap_elem { + u8 mac_cap_info[2]; + u8 phy_cap_info[8]; +} __packed; + +/* 802.11be EHT MAC capabilities from P802.11be_D1.3, section 9.4.2.313.2 */ +#define IEEE80211_EHT_MAC_CAP0_NSEP_PRIORITY_ACCESS BIT(0) +#define IEEE80211_EHT_MAC_CAP0_EHT_OM_CONTROL BIT(1) +#define IEEE80211_EHT_MAC_CAP0_TXOP_SHARING_MODE1 BIT(2) +#define IEEE80211_EHT_MAC_CAP0_TXOP_SHARING_MODE2 BIT(3) +#define IEEE80211_EHT_MAC_CAP0_RESTRICTED_TWT BIT(4) +#define IEEE80211_EHT_MAC_CAP0_SCS_TRAFFIC_DESC BIT(5) + +#define IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN GENMASK(7, 6) + +/** + * enum ieee80211_eht_max_mpdu_len - maximum MPDU length that STA is capable of + * receiving + * @EHT_MAX_MPDU_LEN_3895: maximum 3895 octets supported + * @EHT_MAX_MPDU_LEN_7991: maximum 7991 octets supported + * @EHT_MAX_MPDU_LEN_11454: maximum 11454 octets supported + */ +enum ieee80211_eht_max_mpdu_len { + EHT_MAX_MPDU_LEN_3895 = 0, + EHT_MAX_MPDU_LEN_7991, + EHT_MAX_MPDU_LEN_11454, +}; + +/** + * ieee80211_eht_set_max_mpdu_len - set maximum MPDU length that STA is capable + * of receiving + * + * @mac_cap_info: EHT MAC capabilities information field data + * @max_len: maximum MPDU length supported, see &enum ieee80211_eht_max_mpdu_len + * + * Set "Maximum MPDU Length" subfield as encoded in "EHT MAC Capabilities + * Information" field in EHT Capabilities element + */ +static inline void +ieee80211_eht_set_max_mpdu_len(u8 *mac_cap_info, + enum ieee80211_eht_max_mpdu_len max_len) +{ + mac_cap_info[0] |= FIELD_PREP(IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN, + max_len); +} + +/** + * ieee80211_eht_get_max_mpdu_len - get maximum MPDU length that STA is capable + * of receiving + * + * @mac_cap_info: EHT MAC capabilities information field data + * + * Get "Maximum MPDU Length" subfield value from "EHT MAC Capabilities + * Information" field in EHT Capabilities element + * + * Return: maximum MPDU length supported, see &enum ieee80211_eht_max_mpdu_len + */ +static inline enum ieee80211_eht_max_mpdu_len +ieee80211_eht_get_max_mpdu_len(const u8 *mac_cap_info) +{ + return FIELD_GET(IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN, mac_cap_info[0]); +} + +/* 802.11be EHT PHY capabilities from P802.11be_D1.3, section 9.4.2.313.3 */ +#define IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ BIT(1) +#define IEEE80211_EHT_PHY_CAP0_NON_AP_20MHZ_ONLY_STA_242_RU_SUPPORT BIT(2) +#define IEEE80211_EHT_PHY_CAP0_NDP_4x_LTF_AND_3_2US BIT(3) +#define IEEE80211_EHT_PHY_CAP0_PARTIAL_BANDWIDTH_UL_MUMIMO BIT(4) +#define IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER BIT(5) +#define IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE BIT(6) + +/* Beamformee SS for under 80MHz is split between byte #1 and byte #2 */ +#define IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_MAX_STS_UPTO_80MHZ GENMASK(7, 7) +#define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_MAX_STS_UPTO_80MHZ GENMASK(1, 0) +#define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_MAX_STS_160MHZ GENMASK(4, 2) +#define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_MAX_STS_320MHZ GENMASK(7, 5) + +#define IEEE80211_EHT_PHY_CAP2_BEAMFORMER_NUM_SND_DIM_UPTO_80MHZ \ + GENMASK(2, 0) +#define IEEE80211_EHT_PHY_CAP2_BEAMFORMER_NUM_SND_DIM_160MHZ GENMASK(5, 3) + +/* + * Number of sounding dimensions supported for 320MHz is split + * between byte #2 and byte #3 + */ +#define IEEE80211_EHT_PHY_CAP2_BEAMFORMER_NUM_SND_DIM_320MHZ GENMASK(7, 6) +#define IEEE80211_EHT_PHY_CAP3_BEAMFORMER_NUM_SND_DIM_320MHZ GENMASK(0, 0) + +#define IEEE80211_EHT_PHY_CAP3_NG16_SU_FEEDBACK BIT(1) +#define IEEE80211_EHT_PHY_CAP3_NG16_MU_FEEDBACK BIT(2) + +#define IEEE80211_EHT_PHY_CAP3_CODEBOOK_SIZE_42_SU BIT(3) +#define IEEE80211_EHT_PHY_CAP3_CODEBOOK_SIZE_75_MU BIT(4) + +#define IEEE80211_EHT_PHY_CAP3_TRIG_SU_BEAMFORMER_FB BIT(5) +#define IEEE80211_EHT_PHY_CAP3_TRIG_MU_BEAMFORMER_FB BIT(6) +#define IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FB BIT(7) + +#define IEEE80211_EHT_PHY_CAP4_PARTIAL_BANDWIDTH_DL_MUMIMO BIT(0) +#define IEEE80211_EHT_PHY_CAP4_PSR_BASED_SR BIT(1) +#define IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACTOR_AR BIT(2) +#define IEEE80211_EHT_PHY_CAP4_MU_PPDU_4XLTF_AND_08_US_GI BIT(3) + +#define IEEE80211_EHT_PHY_CAP4_MAX_NC GENMASK(7, 4) + +#define IEEE80211_EHT_PHY_CAP5_NON_TRIGGERED_CQI_FEEDBACK BIT(0) +#define IEEE80211_EHT_PHY_CAP5_TX_1024_4096_QAM_LESS_THAN_242_TONE_RU BIT(1) +#define IEEE80211_EHT_PHY_CAP5_RX_1024_4096_QAM_LESS_THAN_242_TONE_RU BIT(2) +#define IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT BIT(3) + +#define IEEE80211_EHT_PHY_CAP5_NOMINAL_PKT_PADDING GENMASK(5, 4) + +/* Maximum Number Of Supported EHT-LTFs is split between byte 5 and byte 6 */ +#define IEEE80211_EHT_PHY_CAP5_MAX_EHT_LTF_SUPP BIT(6) +#define IEEE80211_EHT_PHY_CAP5_MAX_EHT_LTF_SUPP_SU GENMASK(7, 7) +#define IEEE80211_EHT_PHY_CAP6_MAX_EHT_LTF_SUPP_SU_RESERVED GENMASK(0, 0) +#define IEEE80211_EHT_PHY_CAP6_MAX_EHT_LTF_SUPP_MU GENMASK(2, 1) + +#define IEEE80211_EHT_PHY_CAP6_MCS15_52_26_TONE_106_26_TONE_SUPP BIT(3) +#define IEEE80211_EHT_PHY_CAP6_MCS15_484_242_TONE_80MHZ_SUPP BIT(4) +#define IEEE80211_EHT_PHY_CAP6_MCS15_996_484_TONE_160MHZ_SUPP BIT(5) +#define IEEE80211_EHT_PHY_CAP6_MCS15_3X996_TONE_320MHZ_SUPP BIT(6) +#define IEEE80211_EHT_PHY_CAP6_EHT_DUP_SUPP_6GHZ BIT(7) + +#define IEEE80211_EHT_PHY_CAP7_20MHZ_STA_NDP_WIDE_BW_SUPP BIT(0) +#define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_UNDER_80MHZ BIT(1) +#define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ BIT(2) +#define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ BIT(3) +#define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_MU_BEAMFORMER_UNDER_80MHZ BIT(4) +#define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_MU_BEAMFORMER_160MHZ BIT(5) +#define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_MU_BEAMFORMER_320MHZ BIT(6) +#define IEEE80211_EHT_PHY_CAP7_TB_SND_FB_RATE_LIMIT BIT(7) + +/** + * enum ieee80211_eht_beamformee_max_sts - maximum number of spatial streams + * that the STA is capable of receiving in an EHT sounding NDP. Minimal + * allowed spatial streams is 4. + * @EHT_BEAMFORMEE_MAX_STS_4: 4 spatial streams supported + * @EHT_BEAMFORMEE_MAX_STS_5: 5 spatial streams supported + * @EHT_BEAMFORMEE_MAX_STS_6: 6 spatial streams supported + * @EHT_BEAMFORMEE_MAX_STS_7: 7 spatial streams supported + * @EHT_BEAMFORMEE_MAX_STS_8: 8 spatial streams supported + */ +enum ieee80211_eht_beamformee_max_sts { + EHT_BEAMFORMEE_MAX_STS_4 = 3, + EHT_BEAMFORMEE_MAX_STS_5 = 4, + EHT_BEAMFORMEE_MAX_STS_6 = 5, + EHT_BEAMFORMEE_MAX_STS_7 = 6, + EHT_BEAMFORMEE_MAX_STS_8 = 7, +}; + +/** + * ieee80211_eht_beamformee_set_max_sts_upto_80mhz - set maximum number of + * spatial streams that the STA is capable of receiving in an EHT sounding + * NDP for bandwidths upto 80 MHz + * + * @phy_cap_info: EHT PHY capabilities information field data + * @max_sts: maximum number of spatial streams supported, see &enum + * ieee80211_eht_beamformee_max_sts + * + * Set "Beamformee SS upto 80 MHz" subfield as encoded in "EHT PHY Capabilities + * Information" field in EHT Capabilities element + */ +static inline void +ieee80211_eht_beamformee_set_max_sts_upto_80mhz( + u8 *phy_cap_info, + enum ieee80211_eht_beamformee_max_sts max_sts) +{ + phy_cap_info[0] |= + FIELD_PREP(IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_MAX_STS_UPTO_80MHZ, + max_sts); + + phy_cap_info[1] |= + FIELD_PREP(IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_MAX_STS_UPTO_80MHZ, + max_sts >> 1); +} + +/** + * ieee80211_eht_beamformee_get_max_sts_upto_80mhz - get maximum number of + * spatial streams that the STA is capable of receiving in an EHT sounding + * NDP for bandwidths upto 80 MHz + * + * @phy_cap_info: EHT PHY capabilities information field data + * + * Get "Beamformee SS upto 80 MHz" subfield value from "EHT PHY Capabilities + * Information" field in EHT Capabilities element + * + * Return: maximum number of spatial streams supported, see &enum + * ieee80211_eht_beamformee_max_sts + */ +static inline enum ieee80211_eht_beamformee_max_sts +ieee80211_eht_beamformee_get_max_sts_upto_80mhz(const u8 *phy_cap_info) +{ + + u8 max_sts = FIELD_GET( + IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_MAX_STS_UPTO_80MHZ, + phy_cap_info[0]); + + max_sts += FIELD_GET( + IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_MAX_STS_UPTO_80MHZ, + phy_cap_info[1]) << 1; + + return max_sts; +} + +/** + * ieee80211_eht_beamformee_set_max_sts_160mhz - set maximum number of spatial + * streams that the STA is capable of receiving in an EHT sounding NDP for + * bandwidth 160 MHz + * + * @phy_cap_info: EHT PHY capabilities information field data + * @max_sts: maximum number of spatial streams supported, see &enum + * ieee80211_eht_beamformee_max_sts + * + * Set "Beamformee SS for 160 MHz" subfield as encoded in "EHT PHY Capabilities + * Information" field in EHT Capabilities element + */ +static inline void +ieee80211_eht_beamformee_set_max_sts_160mhz( + u8 *phy_cap_info, + enum ieee80211_eht_beamformee_max_sts max_sts) +{ + phy_cap_info[1] |= + FIELD_PREP(IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_MAX_STS_160MHZ, max_sts); +} + +/** + * ieee80211_eht_beamformee_get_max_sts_160mhz - get maximum number of spatial + * streams that the STA is capable of receiving in an EHT sounding NDP for + * bandwidth 160 MHz + * + * @phy_cap_info: EHT PHY capabilities information field data + * + * Get "Beamformee SS for 160 MHz" subfield value from "EHT PHY Capabilities + * Information" field in EHT Capabilities element + * + * Return: maximum number of spatial streams supported, see &enum + * ieee80211_eht_beamformee_max_sts + */ +static inline enum ieee80211_eht_beamformee_max_sts +ieee80211_eht_beamformee_get_max_sts_160mhz(const u8 *phy_cap_info) +{ + + return FIELD_GET(IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_MAX_STS_160MHZ, + phy_cap_info[1]); +} + +/** + * ieee80211_eht_beamformee_set_max_sts_320mhz - set maximum number of spatial + * streams that the STA is capable of receiving in an EHT sounding NDP for + * bandwidth 320 MHz + * + * @phy_cap_info: EHT PHY capabilities information field data + * @max_sts: maximum number of spatial streams supported, see &enum + * ieee80211_eht_beamformee_max_sts + * + * Set "Beamformee SS for 320 MHz" subfield as encoded in "EHT PHY Capabilities + * Information" field in EHT Capabilities element + */ +static inline void +ieee80211_eht_beamformee_set_max_sts_320mhz( + u8 *phy_cap_info, + enum ieee80211_eht_beamformee_max_sts max_sts) +{ + phy_cap_info[1] |= + FIELD_PREP(IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_MAX_STS_320MHZ, max_sts); +} + +/** + * ieee80211_eht_beamformee_get_max_sts_320mhz - get maximum number of spatial + * streams that the STA is capable of receiving in an EHT sounding NDP for + * bandwidth 320 MHz + * + * @phy_cap_info: EHT PHY capabilities information field data + * + * Get "Beamformee SS for 320 MHz" subfield value from "EHT PHY Capabilities + * Information" field in EHT Capabilities element + * + * Return: maximum number of spatial streams supported, see &enum + * ieee80211_eht_beamformee_max_sts + */ +static inline enum ieee80211_eht_beamformee_max_sts +ieee80211_eht_beamformee_get_max_sts_320mhz(const u8 *phy_cap_info) +{ + + return FIELD_GET(IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_MAX_STS_320MHZ, + phy_cap_info[1]); +} + +/** + * enum ieee80211_eht_beamformer_snd_dim - Beamformer number of supported + * sounding dimensions + * @EHT_BEAMFORMER_SND_DIM_1: 1 sounding dimension supported + * @EHT_BEAMFORMER_SND_DIM_2: 2 sounding dimensions supported + * @EHT_BEAMFORMER_SND_DIM_3: 3 sounding dimensions supported + * @EHT_BEAMFORMER_SND_DIM_4: 4 sounding dimensions supported + * @EHT_BEAMFORMER_SND_DIM_5: 5 sounding dimensions supported + * @EHT_BEAMFORMER_SND_DIM_6: 6 sounding dimensions supported + * @EHT_BEAMFORMER_SND_DIM_7: 7 sounding dimensions supported + * @EHT_BEAMFORMER_SND_DIM_8: 8 sounding dimensions supported + */ +enum ieee80211_eht_beamformer_snd_dim { + EHT_BEAMFORMER_SND_DIM_1 = 0, + EHT_BEAMFORMER_SND_DIM_2, + EHT_BEAMFORMER_SND_DIM_3, + EHT_BEAMFORMER_SND_DIM_4, + EHT_BEAMFORMER_SND_DIM_5, + EHT_BEAMFORMER_SND_DIM_6, + EHT_BEAMFORMER_SND_DIM_7, + EHT_BEAMFORMER_SND_DIM_8, +}; + +/** + * ieee80211_eht_set_snd_dim_upto_80mhz - set number of sounding dimensions + * supported upto 80 MHz + * + * @phy_cap_info: EHT PHY capabilities information field data + * @num_snd_dim: number of sounding dimensions supported, see &enum + * ieee80211_eht_beamformer_snd_dim + * + * Set "Number Of Sounding Dimensions for upto 80 MHz" subfield as encoded in + * "EHT PHY Capabilities Information" field in EHT Capabilities element + */ +static inline void +ieee80211_eht_set_snd_dim_upto_80mhz( + u8 *phy_cap_info, + enum ieee80211_eht_beamformer_snd_dim num_snd_dim) +{ + phy_cap_info[2] |= + FIELD_PREP(IEEE80211_EHT_PHY_CAP2_BEAMFORMER_NUM_SND_DIM_UPTO_80MHZ, + num_snd_dim); +} + +/** + * ieee80211_eht_get_snd_dim_upto_80mhz - get number of sounding dimensions + * supported upto 80 MHz + * + * @phy_cap_info: EHT PHY capabilities information field data + * + * Get "Number Of Sounding Dimensions upto 80 MHz" subfield value from "EHT PHY + * Capabilities Information" field in EHT Capabilities element + * + * Return: number of sounding dimensions supported, see &enum + * ieee80211_eht_beamformer_snd_dim + */ +static inline enum ieee80211_eht_beamformer_snd_dim +ieee80211_eht_get_snd_dim_upto_80mhz(const u8 *phy_cap_info) +{ + return FIELD_GET( + IEEE80211_EHT_PHY_CAP2_BEAMFORMER_NUM_SND_DIM_UPTO_80MHZ, + phy_cap_info[2]); +} + +/** + * ieee80211_eht_set_snd_dim_160mhz - set number of sounding dimensions + * supported upto 160 MHz + * + * @phy_cap_info: EHT PHY capabilities information field data + * @num_snd_dim: number of sounding dimensions supported, see &enum + * ieee80211_eht_beamformer_snd_dim + * + * Set "Number Of Sounding Dimensions for 160 MHz" subfield as encoded in "EHT + * PHY Capabilities Information" field in EHT Capabilities element + */ +static inline void +ieee80211_eht_set_snd_dim_160mhz( + u8 *phy_cap_info, + enum ieee80211_eht_beamformer_snd_dim num_snd_dim) +{ + phy_cap_info[2] |= + FIELD_PREP(IEEE80211_EHT_PHY_CAP2_BEAMFORMER_NUM_SND_DIM_160MHZ, + num_snd_dim); +} + +/** + * ieee80211_eht_get_snd_dim_160mhz - get number of sounding dimensions + * supported for 160 MHz + * + * @phy_cap_info: EHT PHY capabilities information field data + * + * Get "Number Of Sounding Dimensions for 160 MHz" subfield value from "EHT PHY + * Capabilities Information" field in EHT Capabilities element + * + * Return: number of sounding dimensions supported, see &enum + * ieee80211_eht_beamformer_snd_dim + */ +static inline enum ieee80211_eht_beamformer_snd_dim +ieee80211_eht_get_snd_dim_160mhz(const u8 *phy_cap_info) +{ + return FIELD_GET( + IEEE80211_EHT_PHY_CAP2_BEAMFORMER_NUM_SND_DIM_160MHZ, + phy_cap_info[2]); +} + +/** + * ieee80211_eht_set_snd_dim_320mhz - set number of sounding dimensions + * supported for 320 MHz + * + * @phy_cap_info: EHT PHY capabilities information field data + * @num_snd_dim: number of sounding dimensions supported, &enum + * ieee80211_eht_beamformer_snd_dim + * + * Set "Number Of Sounding Dimensions for 320 MHz" subfield as encoded in "EHT + * PHY Capabilities Information" field in EHT Capabilities element + */ +static inline void +ieee80211_eht_set_max_snd_dim_320( + u8 *phy_cap_info, + enum ieee80211_eht_beamformer_snd_dim num_snd_dim) +{ + phy_cap_info[2] |= + FIELD_PREP(IEEE80211_EHT_PHY_CAP2_BEAMFORMER_NUM_SND_DIM_320MHZ, + num_snd_dim); + + phy_cap_info[3] |= + FIELD_PREP(IEEE80211_EHT_PHY_CAP3_BEAMFORMER_NUM_SND_DIM_320MHZ, + num_snd_dim >> 2); +} + +/** + * ieee80211_eht_get_snd_dim_320mhz - get number of sounding dimensions + * supported for 320 MHz + * + * @phy_cap_info: EHT PHY capabilities information field data + * + * Get "Number Of Sounding Dimensions for 320 MHz" subfield value from "EHT + * PHY Capabilities Information" field in EHT Capabilities element + * + * Return: number of sounding dimensions supported, &enum + * ieee80211_eht_beamformer_snd_dim + */ +static inline enum ieee80211_eht_beamformer_snd_dim +ieee80211_eht_get_max_snd_dim_320(const u8 *phy_cap_info) +{ + u8 num_snd_dim = + FIELD_GET(IEEE80211_EHT_PHY_CAP2_BEAMFORMER_NUM_SND_DIM_320MHZ, + phy_cap_info[2]); + + if (FIELD_GET(IEEE80211_EHT_PHY_CAP3_BEAMFORMER_NUM_SND_DIM_320MHZ, + phy_cap_info[3])) + num_snd_dim += 4; + + return num_snd_dim; +} + +/** + * enum ieee80211_eht_max_nc - maximum supported Nc definitions + * @EHT_MAX_NC_1: maximum 1 Nc supported + * @EHT_MAX_NC_2: maximum 2 Nc supported + * @EHT_MAX_NC_3: maximum 3 Nc supported + * @EHT_MAX_NC_4: maximum 4 Nc supported + * @EHT_MAX_NC_5: maximum 5 Nc supported + * @EHT_MAX_NC_6: maximum 6 Nc supported + * @EHT_MAX_NC_7: maximum 7 Nc supported + * @EHT_MAX_NC_8: maximum 8 Nc supported + */ +enum ieee80211_eht_max_nc { + EHT_MAX_NC_1 = 0, + EHT_MAX_NC_2, + EHT_MAX_NC_3, + EHT_MAX_NC_4, + EHT_MAX_NC_5, + EHT_MAX_NC_6, + EHT_MAX_NC_7, + EHT_MAX_NC_8, +}; + +/** + * ieee80211_eht_set_max_nc - set maximum supported Nc + * + * @phy_cap_info: EHT PHY capabilities information field data + * @max_nc: Maximum supported Nc, see &enum ieee80211_eht_max_nc + * + * Set "Max Nc" subfield as encoded in "EHT PHY Capabilities Information" field + * in EHT Capabilities element + */ +static inline void +ieee80211_eht_set_max_nc(u8 *phy_cap_info, enum ieee80211_eht_max_nc max_nc) +{ + phy_cap_info[4] |= FIELD_PREP(IEEE80211_EHT_PHY_CAP4_MAX_NC, max_nc); +} + +/** + * ieee80211_eht_get_max_nc - get maximum supported Nc + * @phy_cap_info: EHT PHY capabilities information field data + * + * Get "Max Nc" subfield value from "EHT PHY Capabilities Information" field + * in EHT Capabilities element + * + * Return: Max supported Nc, see &enum ieee80211_eht_max_nc + */ +static inline enum ieee80211_eht_max_nc +ieee80211_eht_get_max_nc(const u8 *phy_cap_info) +{ + return FIELD_GET(IEEE80211_EHT_PHY_CAP4_MAX_NC, phy_cap_info[4]); +} + +/** + * enum ieee80211_eht_nominal_pkt_padding - EHT nominal packet padding + * definitions + * @EHT_NOMINAL_PKT_PADDING_0US - 0 us common nominal packet padding + * @EHT_NOMINAL_PKT_PADDING_8US - 8 us common nominal packet padding + * @EHT_NOMINAL_PKT_PADDING_16US - 16 us common nominal packet padding + * @EHT_NOMINAL_PKT_PADDING_16US_OR_20US - 16 us common nominal packet padding + * for all modes with constellation <= 1024, nss <= 8, RU/MRU <= 2x996 and + * 20 us for all other modes + */ +enum ieee80211_eht_nominal_pkt_padding { + EHT_NOMINAL_PKT_PADDING_0US = 0, + EHT_NOMINAL_PKT_PADDING_8US, + EHT_NOMINAL_PKT_PADDING_16US, + EHT_NOMINAL_PKT_PADDING_16US_OR_20US, +}; + +/** + * ieee80211_eht_set_common_nominal_pkt_padding - set EHT common nominal packet + * padding. + * + * @phy_cap_info: EHT PHY capabilities information field data + * @nominal_pkt_pad: common nominal packet padding, see &enum + * ieee80211_eht_nominal_pkt_padding + * + * Set "Common Nominal Packet Padding" subfield as encoded in "EHT PHY + * Capabilities Information" field in EHT Capabilities element + */ +static inline void +ieee80211_eht_set_common_nominal_pkt_padding( + u8 *phy_cap_info, + enum ieee80211_eht_nominal_pkt_padding nominal_pkt_pad) +{ + phy_cap_info[5] |= + FIELD_PREP(IEEE80211_EHT_PHY_CAP5_NOMINAL_PKT_PADDING, nominal_pkt_pad); +} + +/** + * ieee80211_eht_get_common_nominal_pkt_padding - get EHT common nominal packet + * padding. + * + * @phy_cap_info: EHT PHY capabilities information field data + * + * Set "Common Nominal Packet Padding" subfield value from "EHT PHY Capabilities + * Information" field in EHT Capabilities element + * + * Return: EHT common nominal packet padding capability, see &enum + * ieee80211_eht_nominal_pkt_padding + */ +static inline enum ieee80211_eht_nominal_pkt_padding +ieee80211_eht_get_common_nominal_pkt_padding(const u8 *phy_cap_info) +{ + return FIELD_GET(IEEE80211_EHT_PHY_CAP5_NOMINAL_PKT_PADDING, + phy_cap_info[5]); +} + +/** + * enum ieee80211_eht_max_ltf_supp - EHT maximum LTF support definitions + * @EHT_MAX_4XLTF_SUPP - Maximum of four EHT-LTFs supported + * @EHT_MAX_8XLTF_SUPP - Maximum of eight EHT-LTFs supported + */ +enum ieee80211_eht_max_ltf_supp { + EHT_MAX_4XLTF_SUPP = 0, + EHT_MAX_8XLTF_SUPP, +}; + +/** + * ieee80211_eht_set_max_eht_ltf_supp - set maximum number of supported EHT-LTFs + * + * @phy_cap_info: EHT PHY capabilities information field data + * @mu: Multiple user configuration + * @max_ltf: Maximum number of EHT-LTFs supported, see &enum + * ieee80211_eht_max_ltf_supp + * + * Set "Maximum Number Of Supported EHT-LTFs" subfield as encoded in "EHT PHY + * Capabilities Information" field in EHT Capabilities element + */ +static inline void +ieee80211_eht_set_max_eht_ltf_supp(u8 *phy_cap_info, bool mu, + enum ieee80211_eht_max_ltf_supp max_ltf) +{ + + if (mu) { + phy_cap_info[6] |= + FIELD_PREP(IEEE80211_EHT_PHY_CAP6_MAX_EHT_LTF_SUPP_MU, max_ltf); + return; + } + + phy_cap_info[5] |= + FIELD_PREP(IEEE80211_EHT_PHY_CAP5_MAX_EHT_LTF_SUPP_SU, max_ltf); +} + +/** + * ieee80211_eht_get_max_eht_ltf_supp - get maximum number of supported EHT-LTFs + * + * @phy_cap_info: EHT PHY capabilities information field data + * @mu: Multiple user configuration + * + * Get "Maximum Number Of Supported EHT-LTFs" subfield value from "EHT PHY + * Capabilities Information" field in EHT Capabilities element + * + * Return: Maximum number of EHT-LTFs supported, see &enum + * ieee80211_eht_max_ltf_supp + */ +static inline enum ieee80211_eht_max_ltf_supp +ieee80211_eht_get_max_eht_ltf_supp(const u8 *phy_cap_info, bool mu) +{ + if (mu) + return FIELD_GET(IEEE80211_EHT_PHY_CAP6_MAX_EHT_LTF_SUPP_MU, + phy_cap_info[6]); + + return FIELD_GET(IEEE80211_EHT_PHY_CAP5_MAX_EHT_LTF_SUPP_SU, + phy_cap_info[5]); +} + +/** + * ieee80211_eht_mcs_nss_size - Get EHT MCS NSS Support Field size + * + * @eht_cap: EHT capabilities element + * @he_cap: HE capabilities element + * + * Calculate Tx/Rx EHT MCS NSS Support Field size in EHT capabilities IE + * + * Return: EHT MCS NSS Support Field size + */ +static inline u8 +ieee80211_eht_mcs_nss_size(const struct ieee80211_eht_cap_elem *eht_cap, + const struct ieee80211_he_cap_elem *he_cap) +{ + if ((he_cap->phy_cap_info[0] & + (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) == 0) + return 4; + + if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) + return 9; + + if (he_cap->phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) + return 6; + + return 3; +} + +/* EHT PPE Thresholds from P802.11be_D1.3, section 9.4.2.313.5 */ +#define IEEE80211_EHT_PPE_THRES0_NSS GENMASK(3, 0) + +/* RU Index Bitmask is split between byte 0 and byte 1 */ +#define IEEE80211_EHT_PPE_THRES0_RU_INDEX GENMASK(7, 4) +#define IEEE80211_EHT_PPE_THRES1_RU_INDEX BIT(0) + +/* PPE Thresholds Information subfields size in number of bits */ +#define IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE 9 +#define IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE 6 + +/** + * ieee80211_eht_ppe_size - Get EHT PPE Thresholds Info Field size + * + * @ppe_thres_hdr: Header bytes of PPE Thresholds field + * @phy_cap_info: EHT PHY capabilities information + * + * Calculate EHT PPE Thresholds Info Field size in EHT capabilities IE + * + * Return: EHT PPE Thresholds Info Field size + */ +static inline u8 +ieee80211_eht_ppe_size(const u8 *ppe_thres_hdr, const u8 *phy_cap_info) +{ + u8 n; + + if ((phy_cap_info[5] & + IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) == 0) + return 0; + + n = hweight8(FIELD_GET(IEEE80211_EHT_PPE_THRES0_RU_INDEX, + ppe_thres_hdr[0])); + n += hweight8(FIELD_GET(IEEE80211_EHT_PPE_THRES1_RU_INDEX, + ppe_thres_hdr[1])); + + n *= (1 + FIELD_GET(IEEE80211_EHT_PPE_THRES0_NSS, ppe_thres_hdr[0])); + + /** + * Each pair is 6 bits, and we need to add the 9 "header" bits to the + * total size. + */ + n = (n * IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE) + + IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE; + n = DIV_ROUND_UP(n, 8); + + return n; +} + /* Authentication algorithms */ #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 @@ -3054,6 +3755,7 @@ enum ieee80211_eid_ext { WLAN_EID_EXT_SHORT_SSID_LIST = 58, WLAN_EID_EXT_HE_6GHZ_CAPA = 59, WLAN_EID_EXT_UL_MU_POWER_CAPA = 60, + WLAN_EID_EXT_EHT_CAPABILITY = 108, }; /* Action category code */ From patchwork Wed Dec 22 09:04:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Veerendranath Jakkam X-Patchwork-Id: 12691303 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AA89BC433FE for ; Wed, 22 Dec 2021 09:05:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239562AbhLVJFo (ORCPT ); Wed, 22 Dec 2021 04:05:44 -0500 Received: from alexa-out-sd-02.qualcomm.com ([199.106.114.39]:34949 "EHLO alexa-out-sd-02.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239199AbhLVJFn (ORCPT ); Wed, 22 Dec 2021 04:05:43 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1640163943; x=1671699943; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=a50NXRWRzzVYUxVBgRjgm9A++qM8KC6+15UYVkPwD7A=; b=CRiUaT6oQsyzsCrvb+rxIzBVBYA6lwEWebvJ9KJ/WeD2r0uTCNuuD2Dl GukLuKxj46ctJa8tAIkdepMusiT0hw77LqjdMTOycQ507W6k4KpTxMx9u L1fyfBTnyJ5ST7by/KSAW4KvwUKBz+zh8nf8EvirobxJMHySmOemMsdUe w=; Received: from unknown (HELO ironmsg02-sd.qualcomm.com) ([10.53.140.142]) by alexa-out-sd-02.qualcomm.com with ESMTP; 22 Dec 2021 01:05:43 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.47.97.222]) by ironmsg02-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Dec 2021 01:05:43 -0800 Received: from nalasex01a.na.qualcomm.com (10.47.209.196) by nasanex01c.na.qualcomm.com (10.47.97.222) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Wed, 22 Dec 2021 01:05:43 -0800 Received: from hu-vjakkam-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Wed, 22 Dec 2021 01:05:40 -0800 From: Veerendranath Jakkam To: CC: , , , , , , Subject: [PATCH 2/6] nl80211: add support to advertise driver's EHT capabilities Date: Wed, 22 Dec 2021 14:34:39 +0530 Message-ID: <1640163883-12696-3-git-send-email-quic_vjakkam@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640163883-12696-1-git-send-email-quic_vjakkam@quicinc.com> References: <1640163883-12696-1-git-send-email-quic_vjakkam@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Vikram Kandukuri Add nl80211 support to advertise EHT capabilities to the userspace. Add new attributes in enum nl80211_band_iftype_attr to indicate EHT MAC capabilities, PHY capabilities, supported MCC-NSS set and PPE threshold fields. Signed-off-by: Vikram Kandukuri Co-authored-by: Aloka Dixit Signed-off-by: Aloka Dixit Co-authored-by: Veerendranath Jakkam Signed-off-by: Veerendranath Jakkam --- include/net/cfg80211.h | 56 ++++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/nl80211.h | 12 ++++++++++ net/wireless/nl80211.c | 17 ++++++++++++++ 3 files changed, 85 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d19e48f..df197c6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -361,6 +361,28 @@ struct ieee80211_sta_he_cap { }; /** + * struct ieee80211_sta_eht_cap - STA's EHT capabilities + * + * This structure describes parameters needed to describe 802.11be EHT + * capabilities for a STA. + * + * @has_eht: true if EHT data is valid. + * @eht_cap_elem: Fixed portion of the EHT capabilities element. + * @mcs_nss: The supported NSS/MCS combinations. + * @mcs_nss_len: Length of NSS/MCS combinations data. + * @ppe_thres: Holds the PPE Thresholds data. + * @ppe_thres_len: Length PPE Thresholds data. + */ +struct ieee80211_sta_eht_cap { + bool has_eht; + struct ieee80211_eht_cap_elem eht_cap_elem; + u8 *mcs_nss; + u8 mcs_nss_len; + u8 *ppe_thres; + u8 ppe_thres_len; +}; + +/** * struct ieee80211_sband_iftype_data - sband data per interface type * * This structure encapsulates sband data that is relevant for the @@ -374,6 +396,7 @@ struct ieee80211_sta_he_cap { * @vendor_elems: vendor element(s) to advertise * @vendor_elems.data: vendor element(s) data * @vendor_elems.len: vendor element(s) length + * @eht_cap: holds the EHT capabilities. */ struct ieee80211_sband_iftype_data { u16 types_mask; @@ -383,6 +406,7 @@ struct ieee80211_sband_iftype_data { const u8 *data; unsigned int len; } vendor_elems; + struct ieee80211_sta_eht_cap eht_cap; }; /** @@ -522,6 +546,38 @@ ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband, } /** + * ieee80211_get_eht_iftype_cap - return EHT capabilities for an sband's iftype + * @sband: the sband to search for the iftype on + * @iftype: enum nl80211_iftype + * + * Return: pointer to the struct ieee80211_sta_eht_cap, or NULL is none found + */ +static inline const struct ieee80211_sta_eht_cap * +ieee80211_get_eht_iftype_cap(const struct ieee80211_supported_band *sband, + u8 iftype) +{ + const struct ieee80211_sband_iftype_data *data = + ieee80211_get_sband_iftype_data(sband, iftype); + + if (data && data->eht_cap.has_eht) + return &data->eht_cap; + + return NULL; +} + +/** + * ieee80211_get_eht_sta_cap - return EHT capabilities for an sband's STA + * @sband: the sband to search for the STA on + * + * Return: pointer to the struct ieee80211_sta_eht_cap, or NULL is none found + */ +static inline const struct ieee80211_sta_eht_cap * +ieee80211_get_eht_sta_cap(const struct ieee80211_supported_band *sband) +{ + return ieee80211_get_eht_iftype_cap(sband, NL80211_IFTYPE_STATION); +} + +/** * ieee80211_get_he_iftype_cap - return HE capabilities for an sband's iftype * @sband: the sband to search for the iftype on * @iftype: enum nl80211_iftype diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index f1a9d65..a709f5c 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3766,6 +3766,14 @@ enum nl80211_mpath_info { * given for all 6 GHz band channels * @NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS: vendor element capabilities that are * advertised on this band/for this iftype (binary) + * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC: EHT MAC capabilities as in EHT + * capabilities IE + * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY: EHT PHY capabilities as in EHT + * capabilities IE + * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET: EHT supported NSS/MCS as in EHT + * capabilities IE + * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE: EHT PPE thresholds information as + * defined in EHT capabilities IE * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band attribute currently defined */ @@ -3779,6 +3787,10 @@ enum nl80211_band_iftype_attr { NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS, + NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC, + NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY, + NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET, + NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE, /* keep last */ __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 578bff9..0ece4d3 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1729,6 +1729,7 @@ nl80211_send_iftype_data(struct sk_buff *msg, const struct ieee80211_sband_iftype_data *iftdata) { const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap; + const struct ieee80211_sta_eht_cap *eht_cap = &iftdata->eht_cap; if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES, iftdata->types_mask)) @@ -1755,6 +1756,22 @@ nl80211_send_iftype_data(struct sk_buff *msg, &iftdata->he_6ghz_capa)) return -ENOBUFS; + if (eht_cap->has_eht) { + if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC, + sizeof(eht_cap->eht_cap_elem.mac_cap_info), + eht_cap->eht_cap_elem.mac_cap_info) || + nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY, + sizeof(eht_cap->eht_cap_elem.phy_cap_info), + eht_cap->eht_cap_elem.phy_cap_info) || + (eht_cap->mcs_nss_len && + nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET, + eht_cap->mcs_nss_len, eht_cap->mcs_nss)) || + (eht_cap->ppe_thres_len && + nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE, + eht_cap->ppe_thres_len, eht_cap->ppe_thres))) + return -ENOBUFS; + } + if (iftdata->vendor_elems.data && iftdata->vendor_elems.len && nla_put(msg, NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS, iftdata->vendor_elems.len, iftdata->vendor_elems.data)) From patchwork Wed Dec 22 09:04:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Veerendranath Jakkam X-Patchwork-Id: 12691305 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9F768C433F5 for ; Wed, 22 Dec 2021 09:05:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239199AbhLVJFr (ORCPT ); Wed, 22 Dec 2021 04:05:47 -0500 Received: from alexa-out-sd-01.qualcomm.com ([199.106.114.38]:15816 "EHLO alexa-out-sd-01.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232940AbhLVJFq (ORCPT ); Wed, 22 Dec 2021 04:05:46 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1640163946; x=1671699946; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=JQWk4qmhrE5bJfduF1Yzj6Lqav4r9hLGdSjNxk5G45k=; b=HkpH2ikIlTf4fWSDd1cxgcgpNJ8sTxklZIU/hnCQnRVAbwEowGTse0r3 HYIZqTEu4sD4oD9aSR4bV1G5svX/ZXsia2aFsK41tvhnUjM3cabre1oP4 sj4VFZmnOhJBV2j3KSpkAzDIzIf3RjqDrR6nLbVKCBuo3Bw8quwo4Nu5t U=; Received: from unknown (HELO ironmsg-SD-alpha.qualcomm.com) ([10.53.140.30]) by alexa-out-sd-01.qualcomm.com with ESMTP; 22 Dec 2021 01:05:46 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.47.97.222]) by ironmsg-SD-alpha.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Dec 2021 01:05:46 -0800 Received: from nalasex01a.na.qualcomm.com (10.47.209.196) by nasanex01c.na.qualcomm.com (10.47.97.222) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Wed, 22 Dec 2021 01:05:45 -0800 Received: from hu-vjakkam-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Wed, 22 Dec 2021 01:05:43 -0800 From: Veerendranath Jakkam To: CC: , , , , , , Subject: [PATCH 3/6] nl80211: add support to send EHT capabilities from userspace Date: Wed, 22 Dec 2021 14:34:40 +0530 Message-ID: <1640163883-12696-4-git-send-email-quic_vjakkam@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640163883-12696-1-git-send-email-quic_vjakkam@quicinc.com> References: <1640163883-12696-1-git-send-email-quic_vjakkam@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Vikram Kandukuri Add support to process EHT capabilities element passed by the userspace in beacon template and store the pointer in struct cfg80211_ap_settings. Add new attribute NL80211_ATTR_EHT_CAPABILITY to be used by the userspace to pass EHT capabilities of a station trying to associate. Signed-off-by: Vikram Kandukuri Co-authored-by: Aloka Dixit Signed-off-by: Aloka Dixit Co-authored-by: Veerendranath Jakkam Signed-off-by: Veerendranath Jakkam --- include/net/cfg80211.h | 6 ++++++ include/uapi/linux/nl80211.h | 7 +++++++ net/wireless/nl80211.c | 29 ++++++++++++++++++++++++++--- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index df197c6..ce34dd7 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1271,6 +1271,7 @@ struct cfg80211_unsol_bcast_probe_resp { * @ht_cap: HT capabilities (or %NULL if HT isn't enabled) * @vht_cap: VHT capabilities (or %NULL if VHT isn't enabled) * @he_cap: HE capabilities (or %NULL if HE isn't enabled) + * @eht_cap: EHT capabilities (or %NULL if EHT isn't enabled) * @ht_required: stations must support HT * @vht_required: stations must support VHT * @twt_responder: Enable Target Wait Time @@ -1308,6 +1309,7 @@ struct cfg80211_ap_settings { const struct ieee80211_vht_cap *vht_cap; const struct ieee80211_he_cap_elem *he_cap; const struct ieee80211_he_operation *he_oper; + const struct ieee80211_eht_cap_elem *eht_cap; bool ht_required, vht_required, he_required, sae_h2e_required; bool twt_responder; u32 flags; @@ -1473,6 +1475,8 @@ struct sta_txpwr { * @airtime_weight: airtime scheduler weight for this station * @txpwr: transmit power for an associated station * @he_6ghz_capa: HE 6 GHz Band capabilities of station + * @eht_capa: EHT capabilities of station + * @eht_capa_len: the length of the EHT capabilities */ struct station_parameters { const u8 *supported_rates; @@ -1506,6 +1510,8 @@ struct station_parameters { u16 airtime_weight; struct sta_txpwr txpwr; const struct ieee80211_he_6ghz_capa *he_6ghz_capa; + const struct ieee80211_eht_cap_elem *eht_capa; + u8 eht_capa_len; }; /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index a709f5c..c221322 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2659,6 +2659,8 @@ enum nl80211_commands { * enumerated in &enum nl80211_ap_settings_flags. This attribute shall be * used with %NL80211_CMD_START_AP request. * + * @NL80211_ATTR_EHT_CAPABILITY: EHT Capability information element. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -3169,6 +3171,8 @@ enum nl80211_attrs { NL80211_ATTR_AP_SETTINGS_FLAGS, + NL80211_ATTR_EHT_CAPABILITY, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -3225,6 +3229,9 @@ enum nl80211_attrs { #define NL80211_MAX_NR_CIPHER_SUITES 5 #define NL80211_MAX_NR_AKM_SUITES 2 +#define NL80211_EHT_MIN_CAPABILITY_LEN 10 +#define NL80211_EHT_MAX_CAPABILITY_LEN 81 + #define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10 /* default RSSI threshold for scan results if none specified. */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 0ece4d3..dba4002 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -778,6 +778,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED }, [NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG }, [NL80211_ATTR_AP_SETTINGS_FLAGS] = { .type = NLA_U32 }, + [NL80211_ATTR_EHT_CAPABILITY] = + NLA_POLICY_RANGE(NLA_BINARY, + NL80211_EHT_MIN_CAPABILITY_LEN, + NL80211_EHT_MAX_CAPABILITY_LEN), }; /* policy for the key attributes */ @@ -5414,6 +5418,9 @@ static void nl80211_calculate_ap_params(struct cfg80211_ap_settings *params) cap = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_OPERATION, ies, ies_len); if (cap && cap->datalen >= sizeof(*params->he_oper) + 1) params->he_oper = (void *)(cap->data + 1); + cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_CAPABILITY, ies, ies_len); + if (cap && cap->datalen >= sizeof(*params->eht_cap) + 1) + params->eht_cap = (void *)(cap->data + 1); } static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, @@ -6382,7 +6389,7 @@ int cfg80211_check_station_change(struct wiphy *wiphy, if (params->supported_rates) return -EINVAL; if (params->ext_capab || params->ht_capa || params->vht_capa || - params->he_capa) + params->he_capa || params->eht_capa) return -EINVAL; } @@ -6567,6 +6574,17 @@ static int nl80211_parse_sta_channel_info(struct genl_info *info, return 0; } +static void nl80211_parse_sta_eht_capa(struct genl_info *info, + struct station_parameters *params) +{ + if (info->attrs[NL80211_ATTR_EHT_CAPABILITY]) { + params->eht_capa = + nla_data(info->attrs[NL80211_ATTR_EHT_CAPABILITY]); + params->eht_capa_len = + nla_len(info->attrs[NL80211_ATTR_EHT_CAPABILITY]); + } +} + static int nl80211_set_station_tdls(struct genl_info *info, struct station_parameters *params) { @@ -6587,6 +6605,8 @@ static int nl80211_set_station_tdls(struct genl_info *info, nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]); } + nl80211_parse_sta_eht_capa(info, params); + err = nl80211_parse_sta_channel_info(info, params); if (err) return err; @@ -6848,6 +6868,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.he_6ghz_capa = nla_data(info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY]); + nl80211_parse_sta_eht_capa(info, ¶ms); + if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) { params.opmode_notif_used = true; params.opmode_notif = @@ -6891,8 +6913,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.ht_capa = NULL; params.vht_capa = NULL; - /* HE requires WME */ - if (params.he_capa_len || params.he_6ghz_capa) + /* HE and EHT requires WME */ + if (params.he_capa_len || params.he_6ghz_capa || + params.eht_capa_len) return -EINVAL; } From patchwork Wed Dec 22 09:04:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Veerendranath Jakkam X-Patchwork-Id: 12691307 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 67ADEC433F5 for ; Wed, 22 Dec 2021 09:05:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239625AbhLVJFv (ORCPT ); Wed, 22 Dec 2021 04:05:51 -0500 Received: from alexa-out.qualcomm.com ([129.46.98.28]:62064 "EHLO alexa-out.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232940AbhLVJFv (ORCPT ); Wed, 22 Dec 2021 04:05:51 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1640163951; x=1671699951; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=F9C9V9qiB+wdLdPry30fBW0FhzQf2lF8ubMkDvyjxek=; b=Hsk7wt4Bk6WE7T9gVlJO0s7y0ZZhru80f8xm2WeHWFAnq/P9gctHlNBn QShuVvWDWABkOUBg8jsHkHw90QwiOKFWwuR3+u8mV+DpvOEI2Nlw4dZHc gEfuaMZ5lbuIOeJwLMwm4EuxyIDRiqjTJfOzwvRXigW3D7DiO/u578537 4=; Received: from ironmsg07-lv.qualcomm.com ([10.47.202.151]) by alexa-out.qualcomm.com with ESMTP; 22 Dec 2021 01:05:51 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.47.97.222]) by ironmsg07-lv.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Dec 2021 01:05:49 -0800 Received: from nalasex01a.na.qualcomm.com (10.47.209.196) by nasanex01c.na.qualcomm.com (10.47.97.222) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Wed, 22 Dec 2021 01:05:48 -0800 Received: from hu-vjakkam-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Wed, 22 Dec 2021 01:05:46 -0800 From: Veerendranath Jakkam To: CC: , , , , , , Subject: [PATCH 4/6] cfg80211: Add support for EHT 320 MHz channel width Date: Wed, 22 Dec 2021 14:34:41 +0530 Message-ID: <1640163883-12696-5-git-send-email-quic_vjakkam@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640163883-12696-1-git-send-email-quic_vjakkam@quicinc.com> References: <1640163883-12696-1-git-send-email-quic_vjakkam@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Jia Ding Add 320 MHz support in the channel def and center frequency validation with compatible check. Signed-off-by: Jia Ding Co-authored-by: Karthikeyan Periyasamy Signed-off-by: Karthikeyan Periyasamy Co-authored-by: Muna Sinada Signed-off-by: Muna Sinada Co-authored-by: Veerendranath Jakkam Signed-off-by: Veerendranath Jakkam --- include/net/cfg80211.h | 6 +++ include/uapi/linux/nl80211.h | 3 ++ net/wireless/chan.c | 91 ++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 93 insertions(+), 7 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index ce34dd7..eeb2854 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -110,6 +110,11 @@ struct wiphy; * @IEEE80211_CHAN_16MHZ: 16 MHz bandwidth is permitted * on this channel. * + * @IEEE80211_CHAN_NO_320MHZ: If the driver supports 320 MHz on the band, + * this flag indicates that a 320 MHz channel cannot use this + * channel as the control or any of the secondary channels. + * This may be due to the driver or due to regulatory bandwidth + * restrictions. */ enum ieee80211_channel_flags { IEEE80211_CHAN_DISABLED = 1<<0, @@ -131,6 +136,7 @@ enum ieee80211_channel_flags { IEEE80211_CHAN_4MHZ = 1<<16, IEEE80211_CHAN_8MHZ = 1<<17, IEEE80211_CHAN_16MHZ = 1<<18, + IEEE80211_CHAN_NO_320MHZ = 1<<19, }; #define IEEE80211_CHAN_NO_HT40 \ diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index c221322..e4ac7ab 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -4691,6 +4691,8 @@ enum nl80211_key_mode { * @NL80211_CHAN_WIDTH_4: 4 MHz OFDM channel * @NL80211_CHAN_WIDTH_8: 8 MHz OFDM channel * @NL80211_CHAN_WIDTH_16: 16 MHz OFDM channel + * @NL80211_CHAN_WIDTH_320: 320 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * attribute must be provided as well */ enum nl80211_chan_width { NL80211_CHAN_WIDTH_20_NOHT, @@ -4706,6 +4708,7 @@ enum nl80211_chan_width { NL80211_CHAN_WIDTH_4, NL80211_CHAN_WIDTH_8, NL80211_CHAN_WIDTH_16, + NL80211_CHAN_WIDTH_320, }; /** diff --git a/net/wireless/chan.c b/net/wireless/chan.c index eb82205..8b7fb4a 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -181,6 +181,9 @@ static int nl80211_chan_width_to_mhz(enum nl80211_chan_width chan_width) case NL80211_CHAN_WIDTH_160: mhz = 160; break; + case NL80211_CHAN_WIDTH_320: + mhz = 320; + break; default: WARN_ON_ONCE(1); return -1; @@ -271,6 +274,17 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) case NL80211_CHAN_WIDTH_16: /* all checked above */ break; + case NL80211_CHAN_WIDTH_320: + if (chandef->center_freq1 == control_freq + 150 || + chandef->center_freq1 == control_freq + 130 || + chandef->center_freq1 == control_freq + 110 || + chandef->center_freq1 == control_freq + 90 || + chandef->center_freq1 == control_freq - 90 || + chandef->center_freq1 == control_freq - 110 || + chandef->center_freq1 == control_freq - 130 || + chandef->center_freq1 == control_freq - 150) + break; + fallthrough; case NL80211_CHAN_WIDTH_160: if (chandef->center_freq1 == control_freq + 70 || chandef->center_freq1 == control_freq + 50 || @@ -307,7 +321,7 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) EXPORT_SYMBOL(cfg80211_chandef_valid); static void chandef_primary_freqs(const struct cfg80211_chan_def *c, - u32 *pri40, u32 *pri80) + u32 *pri40, u32 *pri80, u32 *pri160) { int tmp; @@ -315,9 +329,11 @@ static void chandef_primary_freqs(const struct cfg80211_chan_def *c, case NL80211_CHAN_WIDTH_40: *pri40 = c->center_freq1; *pri80 = 0; + *pri160 = 0; break; case NL80211_CHAN_WIDTH_80: case NL80211_CHAN_WIDTH_80P80: + *pri160 = 0; *pri80 = c->center_freq1; /* n_P20 */ tmp = (30 + c->chan->center_freq - c->center_freq1)/20; @@ -327,6 +343,7 @@ static void chandef_primary_freqs(const struct cfg80211_chan_def *c, *pri40 = c->center_freq1 - 20 + 40 * tmp; break; case NL80211_CHAN_WIDTH_160: + *pri160 = c->center_freq1; /* n_P20 */ tmp = (70 + c->chan->center_freq - c->center_freq1)/20; /* n_P40 */ @@ -337,6 +354,20 @@ static void chandef_primary_freqs(const struct cfg80211_chan_def *c, tmp /= 2; *pri80 = c->center_freq1 - 40 + 80 * tmp; break; + case NL80211_CHAN_WIDTH_320: + /* n_P20 */ + tmp = (150 + c->chan->center_freq - c->center_freq1) / 20; + /* n_P40 */ + tmp /= 2; + /* freq_P40 */ + *pri40 = c->center_freq1 - 140 + 40 * tmp; + /* n_P80 */ + tmp /= 2; + *pri80 = c->center_freq1 - 120 + 80 * tmp; + /* n_P160 */ + tmp /= 2; + *pri160 = c->center_freq1 - 80 + 160 * tmp; + break; default: WARN_ON_ONCE(1); } @@ -346,7 +377,7 @@ const struct cfg80211_chan_def * cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, const struct cfg80211_chan_def *c2) { - u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80; + u32 c1_pri40, c1_pri80, c2_pri40, c2_pri80, c1_pri160, c2_pri160; /* If they are identical, return */ if (cfg80211_chandef_identical(c1, c2)) @@ -381,14 +412,31 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, c2->width == NL80211_CHAN_WIDTH_20) return c1; - chandef_primary_freqs(c1, &c1_pri40, &c1_pri80); - chandef_primary_freqs(c2, &c2_pri40, &c2_pri80); + chandef_primary_freqs(c1, &c1_pri40, &c1_pri80, &c1_pri160); + chandef_primary_freqs(c2, &c2_pri40, &c2_pri80, &c2_pri160); if (c1_pri40 != c2_pri40) return NULL; - WARN_ON(!c1_pri80 && !c2_pri80); - if (c1_pri80 && c2_pri80 && c1_pri80 != c2_pri80) + if (c1->width == NL80211_CHAN_WIDTH_40) + return c2; + + if (c2->width == NL80211_CHAN_WIDTH_40) + return c1; + + if (c1_pri80 != c2_pri80) + return NULL; + + if (c1->width == NL80211_CHAN_WIDTH_80 && + c2->width > NL80211_CHAN_WIDTH_80) + return c2; + + if (c2->width == NL80211_CHAN_WIDTH_80 && + c1->width > NL80211_CHAN_WIDTH_80) + return c1; + + WARN_ON(!c1_pri160 && !c2_pri160); + if (c1_pri160 && c2_pri160 && c1_pri160 != c2_pri160) return NULL; if (c1->width > c2->width) @@ -960,7 +1008,10 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, struct ieee80211_sta_vht_cap *vht_cap; struct ieee80211_edmg *edmg_cap; u32 width, control_freq, cap; - bool ext_nss_cap, support_80_80 = false; + bool ext_nss_cap, support_80_80 = false, support_320 = false; + const struct ieee80211_sband_iftype_data *iftd; + struct ieee80211_supported_band *sband; + int i; if (WARN_ON(!cfg80211_chandef_valid(chandef))) return false; @@ -1062,6 +1113,32 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, (vht_cap->cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK))) return false; break; + case NL80211_CHAN_WIDTH_320: + prohibited_flags |= IEEE80211_CHAN_NO_320MHZ; + width = 320; + + if (chandef->chan->band != NL80211_BAND_6GHZ) + return false; + + sband = wiphy->bands[NL80211_BAND_6GHZ]; + if (!sband) + return false; + + for (i = 0; i < sband->n_iftype_data; i++) { + iftd = &sband->iftype_data[i]; + if (!iftd->eht_cap.has_eht) + continue; + + if (iftd->eht_cap.eht_cap_elem.phy_cap_info[0] & + IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) { + support_320 = true; + break; + } + } + + if (!support_320) + return false; + break; default: WARN_ON_ONCE(1); return false; From patchwork Wed Dec 22 09:04:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Veerendranath Jakkam X-Patchwork-Id: 12691309 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BF17FC433EF for ; Wed, 22 Dec 2021 09:05:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239727AbhLVJFx (ORCPT ); Wed, 22 Dec 2021 04:05:53 -0500 Received: from alexa-out-sd-02.qualcomm.com ([199.106.114.39]:34981 "EHLO alexa-out-sd-02.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239681AbhLVJFw (ORCPT ); Wed, 22 Dec 2021 04:05:52 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1640163952; x=1671699952; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=BOBKcTa+bHYlARGQNS0zVx10bMD1TK7KWSV1WAgO+Dc=; b=adTMiqSRpG72vGlcNwTa9g2VnZedLr3Duttgh/v4nxrgPY05IyLYb+OV B9a/wRw+UrP/FfG8SFXGNdebED3Mao9czipaR9JjRtwfEDfQJHABwGfDT Y3+D9Ipo5x51c0JDAv8moN6pkBeisfJ3P+oDVkLjW5roF4tcbreYLOIVA 4=; Received: from unknown (HELO ironmsg01-sd.qualcomm.com) ([10.53.140.141]) by alexa-out-sd-02.qualcomm.com with ESMTP; 22 Dec 2021 01:05:52 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.47.97.222]) by ironmsg01-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Dec 2021 01:05:52 -0800 Received: from nalasex01a.na.qualcomm.com (10.47.209.196) by nasanex01c.na.qualcomm.com (10.47.97.222) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Wed, 22 Dec 2021 01:05:51 -0800 Received: from hu-vjakkam-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Wed, 22 Dec 2021 01:05:48 -0800 From: Veerendranath Jakkam To: CC: , , , , , , Subject: [PATCH 5/6] nl80211: add support for 320MHz channel limitation Date: Wed, 22 Dec 2021 14:34:42 +0530 Message-ID: <1640163883-12696-6-git-send-email-quic_vjakkam@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640163883-12696-1-git-send-email-quic_vjakkam@quicinc.com> References: <1640163883-12696-1-git-send-email-quic_vjakkam@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Sriram R Add support to advertise drivers or regulatory limitations on 320 MHz channels to userspace. Signed-off-by: Sriram R Co-authored-by: Karthikeyan Periyasamy Signed-off-by: Karthikeyan Periyasamy Co-authored-by: Veerendranath Jakkam Signed-off-by: Veerendranath Jakkam --- include/uapi/linux/nl80211.h | 5 +++++ net/wireless/nl80211.c | 3 +++ net/wireless/reg.c | 6 ++++++ 3 files changed, 14 insertions(+) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index e4ac7ab..b985cb0 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3942,6 +3942,8 @@ enum nl80211_wmm_rule { * on this channel in current regulatory domain. * @NL80211_FREQUENCY_ATTR_16MHZ: 16 MHz operation is allowed * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_NO_320MHZ: any 320 MHz channel using this channel + * as the primary or any of the secondary channels isn't possible * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number * currently defined * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use @@ -3978,6 +3980,7 @@ enum nl80211_frequency_attr { NL80211_FREQUENCY_ATTR_4MHZ, NL80211_FREQUENCY_ATTR_8MHZ, NL80211_FREQUENCY_ATTR_16MHZ, + NL80211_FREQUENCY_ATTR_NO_320MHZ, /* keep last */ __NL80211_FREQUENCY_ATTR_AFTER_LAST, @@ -4176,6 +4179,7 @@ enum nl80211_sched_scan_match_attr { * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed * @NL80211_RRF_NO_HE: HE operation not allowed + * @NL80211_RRF_NO_320MHZ: 320MHz operation not allowed */ enum nl80211_reg_rule_flags { NL80211_RRF_NO_OFDM = 1<<0, @@ -4194,6 +4198,7 @@ enum nl80211_reg_rule_flags { NL80211_RRF_NO_80MHZ = 1<<15, NL80211_RRF_NO_160MHZ = 1<<16, NL80211_RRF_NO_HE = 1<<17, + NL80211_RRF_NO_320MHZ = 1<<18, }; #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index dba4002..f31a464 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1152,6 +1152,9 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy, if ((chan->flags & IEEE80211_CHAN_16MHZ) && nla_put_flag(msg, NL80211_FREQUENCY_ATTR_16MHZ)) goto nla_put_failure; + if ((chan->flags & IEEE80211_CHAN_NO_320MHZ) && + nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_320MHZ)) + goto nla_put_failure; } if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, diff --git a/net/wireless/reg.c b/net/wireless/reg.c index ec25924..c76cd97 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1238,6 +1238,8 @@ unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd, { unsigned int bw = reg_get_max_bandwidth_from_range(rd, rule); + if (rule->flags & NL80211_RRF_NO_320MHZ) + bw = min_t(unsigned int, bw, MHZ_TO_KHZ(160)); if (rule->flags & NL80211_RRF_NO_160MHZ) bw = min_t(unsigned int, bw, MHZ_TO_KHZ(80)); if (rule->flags & NL80211_RRF_NO_80MHZ) @@ -1611,6 +1613,8 @@ static u32 map_regdom_flags(u32 rd_flags) channel_flags |= IEEE80211_CHAN_NO_160MHZ; if (rd_flags & NL80211_RRF_NO_HE) channel_flags |= IEEE80211_CHAN_NO_HE; + if (rd_flags & NL80211_RRF_NO_320MHZ) + channel_flags |= IEEE80211_CHAN_NO_320MHZ; return channel_flags; } @@ -1773,6 +1777,8 @@ static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd bw_flags |= IEEE80211_CHAN_NO_80MHZ; if (max_bandwidth_khz < MHZ_TO_KHZ(160)) bw_flags |= IEEE80211_CHAN_NO_160MHZ; + if (max_bandwidth_khz < MHZ_TO_KHZ(320)) + bw_flags |= IEEE80211_CHAN_NO_320MHZ; } return bw_flags; } From patchwork Wed Dec 22 09:04:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Veerendranath Jakkam X-Patchwork-Id: 12691311 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C910EC433EF for ; Wed, 22 Dec 2021 09:05:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239763AbhLVJF4 (ORCPT ); Wed, 22 Dec 2021 04:05:56 -0500 Received: from alexa-out.qualcomm.com ([129.46.98.28]:62064 "EHLO alexa-out.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239685AbhLVJFz (ORCPT ); Wed, 22 Dec 2021 04:05:55 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1640163955; x=1671699955; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=Z68mepVh0wkt6OLg4CwFPMFjoEJezoNgBadkCvzhM+Y=; b=aDu/iZ+qIW5q7YTmDPYKqN2OeCOHm4Hk5xe48D0IaXr1UMP31KHSCzKt 1HbeJa/2Yk93jeOT8S81LjY4W7Yph23Nok8gjG7cgdq3qDUETyI/IiHwF BmgvsrgrjEKmrUsc43xUTiDpebTtwHm3huA+PBbBHEj5VTVMuNSO94bmJ o=; Received: from ironmsg09-lv.qualcomm.com ([10.47.202.153]) by alexa-out.qualcomm.com with ESMTP; 22 Dec 2021 01:05:55 -0800 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.47.97.222]) by ironmsg09-lv.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Dec 2021 01:05:55 -0800 Received: from nalasex01a.na.qualcomm.com (10.47.209.196) by nasanex01c.na.qualcomm.com (10.47.97.222) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Wed, 22 Dec 2021 01:05:54 -0800 Received: from hu-vjakkam-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.922.19; Wed, 22 Dec 2021 01:05:51 -0800 From: Veerendranath Jakkam To: CC: , , , , , , Subject: [PATCH 6/6] nl80211: add EHT MCS support Date: Wed, 22 Dec 2021 14:34:43 +0530 Message-ID: <1640163883-12696-7-git-send-email-quic_vjakkam@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1640163883-12696-1-git-send-email-quic_vjakkam@quicinc.com> References: <1640163883-12696-1-git-send-email-quic_vjakkam@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Add support for reporting and calculating EHT bitrates. Signed-off-by: Veerendranath Jakkam --- include/net/cfg80211.h | 11 ++++ include/uapi/linux/nl80211.h | 62 ++++++++++++++++++++ net/wireless/nl80211.c | 18 ++++++ net/wireless/util.c | 131 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 222 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index eeb2854..56ead14 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1595,6 +1595,7 @@ int cfg80211_check_station_change(struct wiphy *wiphy, * @RATE_INFO_FLAGS_HE_MCS: HE MCS information * @RATE_INFO_FLAGS_EDMG: 60GHz MCS in EDMG mode * @RATE_INFO_FLAGS_EXTENDED_SC_DMG: 60GHz extended SC MCS + * @RATE_INFO_FLAGS_EHT_MCS: EHT MCS information */ enum rate_info_flags { RATE_INFO_FLAGS_MCS = BIT(0), @@ -1604,6 +1605,7 @@ enum rate_info_flags { RATE_INFO_FLAGS_HE_MCS = BIT(4), RATE_INFO_FLAGS_EDMG = BIT(5), RATE_INFO_FLAGS_EXTENDED_SC_DMG = BIT(6), + RATE_INFO_FLAGS_EHT_MCS = BIT(7), }; /** @@ -1618,6 +1620,8 @@ enum rate_info_flags { * @RATE_INFO_BW_80: 80 MHz bandwidth * @RATE_INFO_BW_160: 160 MHz bandwidth * @RATE_INFO_BW_HE_RU: bandwidth determined by HE RU allocation + * @RATE_INFO_BW_320: 320 MHz bandwidth + * @RATE_INFO_BW_EHT_RU: bandwidth determined by EHT RU allocation */ enum rate_info_bw { RATE_INFO_BW_20 = 0, @@ -1627,6 +1631,8 @@ enum rate_info_bw { RATE_INFO_BW_80, RATE_INFO_BW_160, RATE_INFO_BW_HE_RU, + RATE_INFO_BW_320, + RATE_INFO_BW_EHT_RU, }; /** @@ -1644,6 +1650,9 @@ enum rate_info_bw { * @he_ru_alloc: HE RU allocation (from &enum nl80211_he_ru_alloc, * only valid if bw is %RATE_INFO_BW_HE_RU) * @n_bonded_ch: In case of EDMG the number of bonded channels (1-4) + * @eht_gi: EHT guard interval (from &enum nl80211_eht_gi) + * @eht_ru_alloc: EHT RU allocation (from &enum nl80211_eht_ru_alloc, + * only valid if bw is %RATE_INFO_BW_EHT_RU) */ struct rate_info { u8 flags; @@ -1655,6 +1664,8 @@ struct rate_info { u8 he_dcm; u8 he_ru_alloc; u8 n_bonded_ch; + u8 eht_gi; + u8 eht_ru_alloc; }; /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index b985cb0..76c70fc 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3400,6 +3400,56 @@ enum nl80211_he_ru_alloc { }; /** + * enum nl80211_eht_gi - EHT guard interval + * @NL80211_RATE_INFO_EHT_GI_0_8: 0.8 usec + * @NL80211_RATE_INFO_EHT_GI_1_6: 1.6 usec + * @NL80211_RATE_INFO_EHT_GI_3_2: 3.2 usec + */ +enum nl80211_eht_gi { + NL80211_RATE_INFO_EHT_GI_0_8, + NL80211_RATE_INFO_EHT_GI_1_6, + NL80211_RATE_INFO_EHT_GI_3_2, +}; + +/** + * enum nl80211_eht_ru_alloc - EHT RU allocation values + * @NL80211_RATE_INFO_EHT_RU_ALLOC_26: 26-tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_52: 52-tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_52P26: 52+26-tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_106: 106-tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_106P26: 106+26 tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_242: 242-tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_484: 484-tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_484P242: 484+242 tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_996: 996-tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_996P484: 996+484 tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242: 996+484+242 tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_2x996: 2x996-tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484: 2x996+484 tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_3x996: 3x996-tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484: 3x996+484 tone RU allocation + * @NL80211_RATE_INFO_EHT_RU_ALLOC_4x996: 4x996-tone RU allocation + */ +enum nl80211_eht_ru_alloc { + NL80211_RATE_INFO_EHT_RU_ALLOC_26, + NL80211_RATE_INFO_EHT_RU_ALLOC_52, + NL80211_RATE_INFO_EHT_RU_ALLOC_52P26, + NL80211_RATE_INFO_EHT_RU_ALLOC_106, + NL80211_RATE_INFO_EHT_RU_ALLOC_106P26, + NL80211_RATE_INFO_EHT_RU_ALLOC_242, + NL80211_RATE_INFO_EHT_RU_ALLOC_484, + NL80211_RATE_INFO_EHT_RU_ALLOC_484P242, + NL80211_RATE_INFO_EHT_RU_ALLOC_996, + NL80211_RATE_INFO_EHT_RU_ALLOC_996P484, + NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242, + NL80211_RATE_INFO_EHT_RU_ALLOC_2x996, + NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484, + NL80211_RATE_INFO_EHT_RU_ALLOC_3x996, + NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484, + NL80211_RATE_INFO_EHT_RU_ALLOC_4x996, +}; + +/** * enum nl80211_rate_info - bitrate information * * These attribute types are used with %NL80211_STA_INFO_TXRATE @@ -3438,6 +3488,13 @@ enum nl80211_he_ru_alloc { * @NL80211_RATE_INFO_HE_DCM: HE DCM value (u8, 0/1) * @NL80211_RATE_INFO_RU_ALLOC: HE RU allocation, if not present then * non-OFDMA was used (u8, see &enum nl80211_he_ru_alloc) + * @NL80211_RATE_INFO_320_MHZ_WIDTH: 320 MHz bitrate + * @NL80211_RATE_INFO_EHT_MCS: EHT MCS index (u8, 0-15) + * @NL80211_RATE_INFO_EHT_NSS: EHT NSS value (u8, 1-8) + * @NL80211_RATE_INFO_EHT_GI: EHT guard interval identifier + * (u8, see &enum nl80211_eht_gi) + * @NL80211_RATE_INFO_EHT_RU_ALLOC: EHT RU allocation, if not present then + * non-OFDMA was used (u8, see &enum nl80211_eht_ru_alloc) * @__NL80211_RATE_INFO_AFTER_LAST: internal use */ enum nl80211_rate_info { @@ -3459,6 +3516,11 @@ enum nl80211_rate_info { NL80211_RATE_INFO_HE_GI, NL80211_RATE_INFO_HE_DCM, NL80211_RATE_INFO_HE_RU_ALLOC, + NL80211_RATE_INFO_320_MHZ_WIDTH, + NL80211_RATE_INFO_EHT_MCS, + NL80211_RATE_INFO_EHT_NSS, + NL80211_RATE_INFO_EHT_GI, + NL80211_RATE_INFO_EHT_RU_ALLOC, /* keep last */ __NL80211_RATE_INFO_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f31a464..10f4fc6 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5946,6 +5946,13 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr) case RATE_INFO_BW_HE_RU: rate_flg = 0; WARN_ON(!(info->flags & RATE_INFO_FLAGS_HE_MCS)); + break; + case RATE_INFO_BW_320: + rate_flg = NL80211_RATE_INFO_320_MHZ_WIDTH; + break; + case RATE_INFO_BW_EHT_RU: + rate_flg = 0; + WARN_ON(!(info->flags & RATE_INFO_FLAGS_EHT_MCS)); } if (rate_flg && nla_put_flag(msg, rate_flg)) @@ -5978,6 +5985,17 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr) nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC, info->he_ru_alloc)) return false; + } else if (info->flags & RATE_INFO_FLAGS_EHT_MCS) { + if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_MCS, info->mcs)) + return false; + if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_NSS, info->nss)) + return false; + if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_GI, info->eht_gi)) + return false; + if (info->bw == RATE_INFO_BW_EHT_RU && + nla_put_u8(msg, NL80211_RATE_INFO_EHT_RU_ALLOC, + info->eht_ru_alloc)) + return false; } nla_nest_end(msg, rate); diff --git a/net/wireless/util.c b/net/wireless/util.c index 41ea65d..327257c 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1428,6 +1428,135 @@ static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate) return result / 10000; } +static u32 cfg80211_calculate_bitrate_eht(struct rate_info *rate) +{ +#define SCALE 6144 + static const u32 mcs_divisors[16] = { + 102399, /* 16.666666... */ + 51201, /* 8.333333... */ + 34134, /* 5.555555... */ + 25599, /* 4.166666... */ + 17067, /* 2.777777... */ + 12801, /* 2.083333... */ + 11769, /* 1.851851... */ + 10239, /* 1.666666... */ + 8532, /* 1.388888... */ + 7680, /* 1.250000... */ + 6828, /* 1.111111... */ + 6144, /* 1.000000... */ + 5690, /* 0.926106... */ + 5120, /* 0.833333... */ + 409600, /* 66.666666... */ + 204800, /* 33.333333... */ + }; + static const u32 rates_996[3] = { 480388888, 453700000, 408333333 }; + static const u32 rates_484[3] = { 229411111, 216666666, 195000000 }; + static const u32 rates_242[3] = { 114711111, 108333333, 97500000 }; + static const u32 rates_106[3] = { 40000000, 37777777, 34000000 }; + static const u32 rates_52[3] = { 18820000, 17777777, 16000000 }; + static const u32 rates_26[3] = { 9411111, 8888888, 8000000 }; + u64 tmp; + u32 result; + + if (WARN_ON_ONCE(rate->mcs > 15)) + return 0; + if (WARN_ON_ONCE(rate->eht_gi > NL80211_RATE_INFO_EHT_GI_3_2)) + return 0; + if (WARN_ON_ONCE(rate->eht_ru_alloc > + NL80211_RATE_INFO_EHT_RU_ALLOC_4x996)) + return 0; + if (WARN_ON_ONCE(rate->nss < 1 || rate->nss > 8)) + return 0; + + /* Bandwidth checks for MCS 14 */ + if (rate->mcs == 14) { + if ((rate->bw != RATE_INFO_BW_EHT_RU && + rate->bw != RATE_INFO_BW_80 && + rate->bw != RATE_INFO_BW_160 && + rate->bw != RATE_INFO_BW_320) || + (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc != NL80211_RATE_INFO_EHT_RU_ALLOC_996 && + rate->eht_ru_alloc != NL80211_RATE_INFO_EHT_RU_ALLOC_2x996 && + rate->eht_ru_alloc != NL80211_RATE_INFO_EHT_RU_ALLOC_4x996)) { + WARN(1, "invalid EHT BW for MCS 14: bw:%d, ru:%d\n", + rate->bw, rate->eht_ru_alloc); + return 0; + } + } + + if (rate->bw == RATE_INFO_BW_320 || + (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_4x996)) + result = 4 * rates_996[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484) + result = 3 * rates_996[rate->eht_gi] + rates_484[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_3x996) + result = 3 * rates_996[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484) + result = 2 * rates_996[rate->eht_gi] + rates_484[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_160 || + (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_2x996)) + result = 2 * rates_996[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == + NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242) + result = rates_996[rate->eht_gi] + rates_484[rate->eht_gi] + + rates_242[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_996P484) + result = rates_996[rate->eht_gi] + rates_484[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_80 || + (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_996)) + result = rates_996[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_484P242) + result = rates_484[rate->eht_gi] + rates_242[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_40 || + (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_484)) + result = rates_484[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_20 || + (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_242)) + result = rates_242[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_106P26) + result = rates_106[rate->eht_gi] + rates_26[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_106) + result = rates_106[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_52P26) + result = rates_52[rate->eht_gi] + rates_26[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_52) + result = rates_52[rate->eht_gi]; + else if (rate->bw == RATE_INFO_BW_EHT_RU && + rate->eht_ru_alloc == NL80211_RATE_INFO_EHT_RU_ALLOC_26) + result = rates_26[rate->eht_gi]; + else { + WARN(1, "invalid EHT MCS: bw:%d, ru:%d\n", + rate->bw, rate->eht_ru_alloc); + return 0; + } + + /* now scale to the appropriate MCS */ + tmp = result; + tmp *= SCALE; + do_div(tmp, mcs_divisors[rate->mcs]); + result = tmp; + + /* and take NSS */ + result = (result * rate->nss) / 8; + + return result / 10000; +} + u32 cfg80211_calculate_bitrate(struct rate_info *rate) { if (rate->flags & RATE_INFO_FLAGS_MCS) @@ -1442,6 +1571,8 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate) return cfg80211_calculate_bitrate_vht(rate); if (rate->flags & RATE_INFO_FLAGS_HE_MCS) return cfg80211_calculate_bitrate_he(rate); + if (rate->flags & RATE_INFO_FLAGS_EHT_MCS) + return cfg80211_calculate_bitrate_eht(rate); return rate->legacy; }