forked from mirrors/linux
		
	cfg80211: Add support for HE
Add support for the HE in cfg80211 and also add userspace API to nl80211 to send rate information out, conforming with P802.11ax_D2.0. Signed-off-by: Liad Kaufman <liad.kaufman@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Ilan Peer <ilan.peer@intel.com> Signed-off-by: Ido Yariv <idox.yariv@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
This commit is contained in:
		
							parent
							
								
									446faa15c6
								
							
						
					
					
						commit
						c4cbaf7973
					
				
					 6 changed files with 817 additions and 5 deletions
				
			
		| 
						 | 
					@ -1539,6 +1539,106 @@ struct ieee80211_vht_operation {
 | 
				
			||||||
	__le16 basic_mcs_set;
 | 
						__le16 basic_mcs_set;
 | 
				
			||||||
} __packed;
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct ieee80211_he_cap_elem - HE capabilities element
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This structure is the "HE capabilities element" fixed fields as
 | 
				
			||||||
 | 
					 * described in P802.11ax_D2.0 section 9.4.2.237.2 and 9.4.2.237.3
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct ieee80211_he_cap_elem {
 | 
				
			||||||
 | 
						u8 mac_cap_info[5];
 | 
				
			||||||
 | 
						u8 phy_cap_info[9];
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_TX_RX_MCS_NSS_DESC_MAX_LEN	5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * enum ieee80211_he_mcs_support - HE MCS support definitions
 | 
				
			||||||
 | 
					 * @IEEE80211_HE_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the
 | 
				
			||||||
 | 
					 *	number of streams
 | 
				
			||||||
 | 
					 * @IEEE80211_HE_MCS_SUPPORT_0_9: MCSes 0-9 are supported
 | 
				
			||||||
 | 
					 * @IEEE80211_HE_MCS_SUPPORT_0_11: MCSes 0-11 are supported
 | 
				
			||||||
 | 
					 * @IEEE80211_HE_MCS_NOT_SUPPORTED: This number of streams isn't supported
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * These definitions are used in each 2-bit subfield of the rx_mcs_*
 | 
				
			||||||
 | 
					 * and tx_mcs_* fields of &struct ieee80211_he_mcs_nss_supp, which are
 | 
				
			||||||
 | 
					 * both split into 8 subfields by number of streams. These values indicate
 | 
				
			||||||
 | 
					 * which MCSes are supported for the number of streams the value appears
 | 
				
			||||||
 | 
					 * for.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum ieee80211_he_mcs_support {
 | 
				
			||||||
 | 
						IEEE80211_HE_MCS_SUPPORT_0_7	= 0,
 | 
				
			||||||
 | 
						IEEE80211_HE_MCS_SUPPORT_0_9	= 1,
 | 
				
			||||||
 | 
						IEEE80211_HE_MCS_SUPPORT_0_11	= 2,
 | 
				
			||||||
 | 
						IEEE80211_HE_MCS_NOT_SUPPORTED	= 3,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct ieee80211_he_mcs_nss_supp - HE Tx/Rx HE MCS NSS Support Field
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This structure holds the data required for the Tx/Rx HE MCS NSS Support Field
 | 
				
			||||||
 | 
					 * described in P802.11ax_D2.0 section 9.4.2.237.4
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @rx_mcs_80: Rx MCS map 2 bits for each stream, total 8 streams, for channel
 | 
				
			||||||
 | 
					 *     widths less than 80MHz.
 | 
				
			||||||
 | 
					 * @tx_mcs_80: Tx MCS map 2 bits for each stream, total 8 streams, for channel
 | 
				
			||||||
 | 
					 *     widths less than 80MHz.
 | 
				
			||||||
 | 
					 * @rx_mcs_160: Rx MCS map 2 bits for each stream, total 8 streams, for channel
 | 
				
			||||||
 | 
					 *     width 160MHz.
 | 
				
			||||||
 | 
					 * @tx_mcs_160: Tx MCS map 2 bits for each stream, total 8 streams, for channel
 | 
				
			||||||
 | 
					 *     width 160MHz.
 | 
				
			||||||
 | 
					 * @rx_mcs_80p80: Rx MCS map 2 bits for each stream, total 8 streams, for
 | 
				
			||||||
 | 
					 *     channel width 80p80MHz.
 | 
				
			||||||
 | 
					 * @tx_mcs_80p80: Tx MCS map 2 bits for each stream, total 8 streams, for
 | 
				
			||||||
 | 
					 *     channel width 80p80MHz.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct ieee80211_he_mcs_nss_supp {
 | 
				
			||||||
 | 
						__le16 rx_mcs_80;
 | 
				
			||||||
 | 
						__le16 tx_mcs_80;
 | 
				
			||||||
 | 
						__le16 rx_mcs_160;
 | 
				
			||||||
 | 
						__le16 tx_mcs_160;
 | 
				
			||||||
 | 
						__le16 rx_mcs_80p80;
 | 
				
			||||||
 | 
						__le16 tx_mcs_80p80;
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct ieee80211_he_operation - HE capabilities element
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This structure is the "HE operation element" fields as
 | 
				
			||||||
 | 
					 * described in P802.11ax_D2.0 section 9.4.2.238
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct ieee80211_he_operation {
 | 
				
			||||||
 | 
						__le32 he_oper_params;
 | 
				
			||||||
 | 
						__le16 he_mcs_nss_set;
 | 
				
			||||||
 | 
						/* Optional 0,1,3 or 4 bytes: depends on @he_oper_params */
 | 
				
			||||||
 | 
						u8 optional[0];
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct ieee80211_he_mu_edca_param_ac_rec - MU AC Parameter Record field
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This structure is the "MU AC Parameter Record" fields as
 | 
				
			||||||
 | 
					 * described in P802.11ax_D2.0 section 9.4.2.240
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct ieee80211_he_mu_edca_param_ac_rec {
 | 
				
			||||||
 | 
						u8 aifsn;
 | 
				
			||||||
 | 
						u8 ecw_min_max;
 | 
				
			||||||
 | 
						u8 mu_edca_timer;
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct ieee80211_mu_edca_param_set - MU EDCA Parameter Set element
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This structure is the "MU EDCA Parameter Set element" fields as
 | 
				
			||||||
 | 
					 * described in P802.11ax_D2.0 section 9.4.2.240
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct ieee80211_mu_edca_param_set {
 | 
				
			||||||
 | 
						u8 mu_qos_info;
 | 
				
			||||||
 | 
						struct ieee80211_he_mu_edca_param_ac_rec ac_be;
 | 
				
			||||||
 | 
						struct ieee80211_he_mu_edca_param_ac_rec ac_bk;
 | 
				
			||||||
 | 
						struct ieee80211_he_mu_edca_param_ac_rec ac_vi;
 | 
				
			||||||
 | 
						struct ieee80211_he_mu_edca_param_ac_rec ac_vo;
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* 802.11ac VHT Capabilities */
 | 
					/* 802.11ac VHT Capabilities */
 | 
				
			||||||
#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895			0x00000000
 | 
					#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895			0x00000000
 | 
				
			||||||
| 
						 | 
					@ -1577,6 +1677,328 @@ struct ieee80211_vht_operation {
 | 
				
			||||||
#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN			0x10000000
 | 
					#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN			0x10000000
 | 
				
			||||||
#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN			0x20000000
 | 
					#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN			0x20000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 802.11ax HE MAC capabilities */
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_HTC_HE				0x01
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_TWT_REQ				0x02
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_TWT_RES				0x04
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_NOT_SUPP		0x00
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_1		0x08
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_2		0x10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_LEVEL_3		0x18
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_MASK			0x18
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_1		0x00
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_2		0x20
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_4		0x40
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_8		0x60
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_16		0x80
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_32		0xa0
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_64		0xc0
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_UNLIMITED	0xe0
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP0_MAX_NUM_FRAG_MSDU_MASK		0xe0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_UNLIMITED		0x00
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_128			0x01
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_256			0x02
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_512			0x03
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_MIN_FRAG_SIZE_MASK		0x03
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_0US		0x00
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_8US		0x04
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US		0x08
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK		0x0c
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_1		0x00
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_2		0x10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_3		0x20
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_4		0x30
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_5		0x40
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_6		0x50
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_7		0x60
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_8		0x70
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_MASK		0x70
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Link adaptation is split between byte HE_MAC_CAP1 and
 | 
				
			||||||
 | 
					 * HE_MAC_CAP2. It should be set only if IEEE80211_HE_MAC_CAP0_HTC_HE
 | 
				
			||||||
 | 
					 * in which case the following values apply:
 | 
				
			||||||
 | 
					 * 0 = No feedback.
 | 
				
			||||||
 | 
					 * 1 = reserved.
 | 
				
			||||||
 | 
					 * 2 = Unsolicited feedback.
 | 
				
			||||||
 | 
					 * 3 = both
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP1_LINK_ADAPTATION			0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP2_LINK_ADAPTATION			0x01
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP2_ALL_ACK				0x02
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP2_UL_MU_RESP_SCHED			0x04
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP2_BSR				0x08
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP2_BCAST_TWT				0x10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP			0x20
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP2_MU_CASCADING			0x40
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP2_ACK_EN				0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP3_GRP_ADDR_MULTI_STA_BA_DL_MU	0x01
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP3_OMI_CONTROL			0x02
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP3_OFDMA_RA				0x04
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The maximum length of an A-MDPU is defined by the combination of the Maximum
 | 
				
			||||||
 | 
					 * A-MDPU Length Exponent field in the HT capabilities, VHT capabilities and the
 | 
				
			||||||
 | 
					 * same field in the HE capabilities.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_USE_VHT	0x00
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_VHT_1		0x08
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_VHT_2		0x10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_RESERVED	0x18
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_MASK		0x18
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP3_A_AMSDU_FRAG			0x20
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP3_FLEX_TWT_SCHED			0x40
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP3_RX_CTRL_FRAME_TO_MULTIBSS		0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP4_BSRP_BQRP_A_MPDU_AGG		0x01
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP4_QTP				0x02
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP4_BQR				0x04
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP4_SR_RESP				0x08
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP4_NDP_FB_REP			0x10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP4_OPS				0x20
 | 
				
			||||||
 | 
					#define IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU			0x40
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 802.11ax HE PHY capabilities */
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP0_DUAL_BAND					0x01
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G		0x02
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G	0x04
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G		0x08
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G	0x10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G	0x20
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G	0x40
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK			0xfe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_80MHZ_ONLY_SECOND_20MHZ	0x01
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_80MHZ_ONLY_SECOND_40MHZ	0x02
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_160MHZ_ONLY_SECOND_20MHZ	0x04
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_160MHZ_ONLY_SECOND_40MHZ	0x08
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK			0x0f
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A				0x10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD			0x20
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US		0x40
 | 
				
			||||||
 | 
					/* Midamble RX Max NSTS is split between byte #2 and byte #3 */
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_MAX_NSTS			0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_MAX_NSTS			0x01
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US			0x02
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ			0x04
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ			0x08
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP2_DOPPLER_TX				0x10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP2_DOPPLER_RX				0x20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Note that the meaning of UL MU below is different between an AP and a non-AP
 | 
				
			||||||
 | 
					 * sta, where in the AP case it indicates support for Rx and in the non-AP sta
 | 
				
			||||||
 | 
					 * case it indicates support for Tx.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO			0x40
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO			0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_NO_DCM			0x00
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_BPSK			0x01
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK			0x02
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_16_QAM			0x03
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK			0x03
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_1				0x00
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_2				0x04
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_NO_DCM			0x00
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_BPSK			0x08
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK			0x10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM			0x18
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK			0x18
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1				0x00
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_2				0x20
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA		0x40
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER				0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE				0x01
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER				0x02
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Minimal allowed value of Max STS under 80MHz is 3 */
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4		0x0c
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_5		0x10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_6		0x14
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_7		0x18
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_8		0x1c
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_MASK	0x1c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Minimal allowed value of Max STS above 80MHz is 3 */
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4		0x60
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_5		0x80
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_6		0xa0
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_7		0xc0
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_8		0xe0
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_MASK	0xe0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_1	0x00
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2	0x01
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_3	0x02
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_4	0x03
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_5	0x04
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_6	0x05
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_7	0x06
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_8	0x07
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK	0x07
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_1	0x00
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2	0x08
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_3	0x10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_4	0x18
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_5	0x20
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_6	0x28
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_7	0x30
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_8	0x38
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK	0x38
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK				0x40
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK				0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU			0x01
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU			0x02
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB			0x04
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB			0x08
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB				0x10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE			0x20
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO		0x40
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT			0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP7_SRP_BASED_SR				0x01
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_AR			0x02
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI		0x04
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP7_MAX_NC_1					0x08
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP7_MAX_NC_2					0x10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP7_MAX_NC_3					0x18
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP7_MAX_NC_4					0x20
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP7_MAX_NC_5					0x28
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP7_MAX_NC_6					0x30
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP7_MAX_NC_7					0x38
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP7_MAX_NC_MASK				0x38
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ			0x40
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ			0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI		0x01
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G		0x02
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU			0x04
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU			0x08
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP8_HE_ER_SU_1XLTF_AND_08_US_GI		0x10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PHY_CAP8_MIDAMBLE_RX_2X_AND_1XLTF			0x20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 802.11ax HE TX/RX MCS NSS Support  */
 | 
				
			||||||
 | 
					#define IEEE80211_TX_RX_MCS_NSS_SUPP_HIGHEST_MCS_POS			(3)
 | 
				
			||||||
 | 
					#define IEEE80211_TX_RX_MCS_NSS_SUPP_TX_BITMAP_POS			(6)
 | 
				
			||||||
 | 
					#define IEEE80211_TX_RX_MCS_NSS_SUPP_RX_BITMAP_POS			(11)
 | 
				
			||||||
 | 
					#define IEEE80211_TX_RX_MCS_NSS_SUPP_TX_BITMAP_MASK			0x07c0
 | 
				
			||||||
 | 
					#define IEEE80211_TX_RX_MCS_NSS_SUPP_RX_BITMAP_MASK			0xf800
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* TX/RX HE MCS Support field Highest MCS subfield encoding */
 | 
				
			||||||
 | 
					enum ieee80211_he_highest_mcs_supported_subfield_enc {
 | 
				
			||||||
 | 
						HIGHEST_MCS_SUPPORTED_MCS7 = 0,
 | 
				
			||||||
 | 
						HIGHEST_MCS_SUPPORTED_MCS8,
 | 
				
			||||||
 | 
						HIGHEST_MCS_SUPPORTED_MCS9,
 | 
				
			||||||
 | 
						HIGHEST_MCS_SUPPORTED_MCS10,
 | 
				
			||||||
 | 
						HIGHEST_MCS_SUPPORTED_MCS11,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Calculate 802.11ax HE capabilities IE Tx/Rx HE MCS NSS Support Field size */
 | 
				
			||||||
 | 
					static inline u8
 | 
				
			||||||
 | 
					ieee80211_he_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u8 count = 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (he_cap->phy_cap_info[0] &
 | 
				
			||||||
 | 
						    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
 | 
				
			||||||
 | 
							count += 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (he_cap->phy_cap_info[0] &
 | 
				
			||||||
 | 
						    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
 | 
				
			||||||
 | 
							count += 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 802.11ax HE PPE Thresholds */
 | 
				
			||||||
 | 
					#define IEEE80211_PPE_THRES_NSS_SUPPORT_2NSS			(1)
 | 
				
			||||||
 | 
					#define IEEE80211_PPE_THRES_NSS_POS				(0)
 | 
				
			||||||
 | 
					#define IEEE80211_PPE_THRES_NSS_MASK				(7)
 | 
				
			||||||
 | 
					#define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_2x966_AND_966_RU	\
 | 
				
			||||||
 | 
						(BIT(5) | BIT(6))
 | 
				
			||||||
 | 
					#define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK		0x78
 | 
				
			||||||
 | 
					#define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS		(3)
 | 
				
			||||||
 | 
					#define IEEE80211_PPE_THRES_INFO_PPET_SIZE			(3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Calculate 802.11ax HE capabilities IE PPE field size
 | 
				
			||||||
 | 
					 * Input: Header byte of ppe_thres (first byte), and HE capa IE's PHY cap u8*
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline u8
 | 
				
			||||||
 | 
					ieee80211_he_ppe_size(u8 ppe_thres_hdr, const u8 *phy_cap_info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u8 n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((phy_cap_info[6] &
 | 
				
			||||||
 | 
						     IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) == 0)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n = hweight8(ppe_thres_hdr &
 | 
				
			||||||
 | 
							     IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK);
 | 
				
			||||||
 | 
						n *= (1 + ((ppe_thres_hdr & IEEE80211_PPE_THRES_NSS_MASK) >>
 | 
				
			||||||
 | 
							   IEEE80211_PPE_THRES_NSS_POS));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Each pair is 6 bits, and we need to add the 7 "header" bits to the
 | 
				
			||||||
 | 
						 * total size.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						n = (n * IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2) + 7;
 | 
				
			||||||
 | 
						n = DIV_ROUND_UP(n, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return n;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* HE Operation defines */
 | 
				
			||||||
 | 
					#define IEEE80211_HE_OPERATION_BSS_COLOR_MASK			0x0000003f
 | 
				
			||||||
 | 
					#define IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK		0x000001c0
 | 
				
			||||||
 | 
					#define IEEE80211_HE_OPERATION_DFLT_PE_DURATION_OFFSET		6
 | 
				
			||||||
 | 
					#define IEEE80211_HE_OPERATION_TWT_REQUIRED			0x00000200
 | 
				
			||||||
 | 
					#define IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK		0x000ffc00
 | 
				
			||||||
 | 
					#define IEEE80211_HE_OPERATION_RTS_THRESHOLD_OFFSET		10
 | 
				
			||||||
 | 
					#define IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR		0x000100000
 | 
				
			||||||
 | 
					#define IEEE80211_HE_OPERATION_VHT_OPER_INFO			0x000200000
 | 
				
			||||||
 | 
					#define IEEE80211_HE_OPERATION_MULTI_BSSID_AP			0x10000000
 | 
				
			||||||
 | 
					#define IEEE80211_HE_OPERATION_TX_BSSID_INDICATOR		0x20000000
 | 
				
			||||||
 | 
					#define IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED		0x40000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size
 | 
				
			||||||
 | 
					 * @he_oper_ie: byte data of the He Operations IE, stating from the the byte
 | 
				
			||||||
 | 
					 *	after the ext ID byte. It is assumed that he_oper_ie has at least
 | 
				
			||||||
 | 
					 *	sizeof(struct ieee80211_he_operation) bytes, checked already in
 | 
				
			||||||
 | 
					 *	ieee802_11_parse_elems_crc()
 | 
				
			||||||
 | 
					 * @return the actual size of the IE data (not including header), or 0 on error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline u8
 | 
				
			||||||
 | 
					ieee80211_he_oper_size(const u8 *he_oper_ie)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ieee80211_he_operation *he_oper = (void *)he_oper_ie;
 | 
				
			||||||
 | 
						u8 oper_len = sizeof(struct ieee80211_he_operation);
 | 
				
			||||||
 | 
						u32 he_oper_params;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Make sure the input is not NULL */
 | 
				
			||||||
 | 
						if (!he_oper_ie)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Calc required length */
 | 
				
			||||||
 | 
						he_oper_params = le32_to_cpu(he_oper->he_oper_params);
 | 
				
			||||||
 | 
						if (he_oper_params & IEEE80211_HE_OPERATION_VHT_OPER_INFO)
 | 
				
			||||||
 | 
							oper_len += 3;
 | 
				
			||||||
 | 
						if (he_oper_params & IEEE80211_HE_OPERATION_MULTI_BSSID_AP)
 | 
				
			||||||
 | 
							oper_len++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Add the first byte (extension ID) to the total length */
 | 
				
			||||||
 | 
						oper_len++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return oper_len;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Authentication algorithms */
 | 
					/* Authentication algorithms */
 | 
				
			||||||
#define WLAN_AUTH_OPEN 0
 | 
					#define WLAN_AUTH_OPEN 0
 | 
				
			||||||
#define WLAN_AUTH_SHARED_KEY 1
 | 
					#define WLAN_AUTH_SHARED_KEY 1
 | 
				
			||||||
| 
						 | 
					@ -1992,6 +2414,11 @@ enum ieee80211_eid_ext {
 | 
				
			||||||
	WLAN_EID_EXT_FILS_WRAPPED_DATA = 8,
 | 
						WLAN_EID_EXT_FILS_WRAPPED_DATA = 8,
 | 
				
			||||||
	WLAN_EID_EXT_FILS_PUBLIC_KEY = 12,
 | 
						WLAN_EID_EXT_FILS_PUBLIC_KEY = 12,
 | 
				
			||||||
	WLAN_EID_EXT_FILS_NONCE = 13,
 | 
						WLAN_EID_EXT_FILS_NONCE = 13,
 | 
				
			||||||
 | 
						WLAN_EID_EXT_FUTURE_CHAN_GUIDANCE = 14,
 | 
				
			||||||
 | 
						WLAN_EID_EXT_HE_CAPABILITY = 35,
 | 
				
			||||||
 | 
						WLAN_EID_EXT_HE_OPERATION = 36,
 | 
				
			||||||
 | 
						WLAN_EID_EXT_UORA = 37,
 | 
				
			||||||
 | 
						WLAN_EID_EXT_HE_MU_EDCA = 38,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Action category code */
 | 
					/* Action category code */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -285,6 +285,41 @@ struct ieee80211_sta_vht_cap {
 | 
				
			||||||
	struct ieee80211_vht_mcs_info vht_mcs;
 | 
						struct ieee80211_vht_mcs_info vht_mcs;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IEEE80211_HE_PPE_THRES_MAX_LEN		25
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct ieee80211_sta_he_cap - STA's HE capabilities
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This structure describes most essential parameters needed
 | 
				
			||||||
 | 
					 * to describe 802.11ax HE capabilities for a STA.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @has_he: true iff HE data is valid.
 | 
				
			||||||
 | 
					 * @he_cap_elem: Fixed portion of the HE capabilities element.
 | 
				
			||||||
 | 
					 * @he_mcs_nss_supp: The supported NSS/MCS combinations.
 | 
				
			||||||
 | 
					 * @ppe_thres: Holds the PPE Thresholds data.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct ieee80211_sta_he_cap {
 | 
				
			||||||
 | 
						bool has_he;
 | 
				
			||||||
 | 
						struct ieee80211_he_cap_elem he_cap_elem;
 | 
				
			||||||
 | 
						struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp;
 | 
				
			||||||
 | 
						u8 ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct ieee80211_sband_iftype_data
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This structure encapsulates sband data that is relevant for the
 | 
				
			||||||
 | 
					 * interface types defined in @types_mask.  Each type in the
 | 
				
			||||||
 | 
					 * @types_mask must be unique across all instances of iftype_data.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @types_mask: interface types mask
 | 
				
			||||||
 | 
					 * @he_cap: holds the HE capabilities
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct ieee80211_sband_iftype_data {
 | 
				
			||||||
 | 
						u16 types_mask;
 | 
				
			||||||
 | 
						struct ieee80211_sta_he_cap he_cap;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * struct ieee80211_supported_band - frequency band definition
 | 
					 * struct ieee80211_supported_band - frequency band definition
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -301,6 +336,11 @@ struct ieee80211_sta_vht_cap {
 | 
				
			||||||
 * @n_bitrates: Number of bitrates in @bitrates
 | 
					 * @n_bitrates: Number of bitrates in @bitrates
 | 
				
			||||||
 * @ht_cap: HT capabilities in this band
 | 
					 * @ht_cap: HT capabilities in this band
 | 
				
			||||||
 * @vht_cap: VHT capabilities in this band
 | 
					 * @vht_cap: VHT capabilities in this band
 | 
				
			||||||
 | 
					 * @n_iftype_data: number of iftype data entries
 | 
				
			||||||
 | 
					 * @iftype_data: interface type data entries.  Note that the bits in
 | 
				
			||||||
 | 
					 *	@types_mask inside this structure cannot overlap (i.e. only
 | 
				
			||||||
 | 
					 *	one occurrence of each type is allowed across all instances of
 | 
				
			||||||
 | 
					 *	iftype_data).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct ieee80211_supported_band {
 | 
					struct ieee80211_supported_band {
 | 
				
			||||||
	struct ieee80211_channel *channels;
 | 
						struct ieee80211_channel *channels;
 | 
				
			||||||
| 
						 | 
					@ -310,8 +350,55 @@ struct ieee80211_supported_band {
 | 
				
			||||||
	int n_bitrates;
 | 
						int n_bitrates;
 | 
				
			||||||
	struct ieee80211_sta_ht_cap ht_cap;
 | 
						struct ieee80211_sta_ht_cap ht_cap;
 | 
				
			||||||
	struct ieee80211_sta_vht_cap vht_cap;
 | 
						struct ieee80211_sta_vht_cap vht_cap;
 | 
				
			||||||
 | 
						u16 n_iftype_data;
 | 
				
			||||||
 | 
						const struct ieee80211_sband_iftype_data *iftype_data;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ieee80211_get_sband_iftype_data - return sband data for a given iftype
 | 
				
			||||||
 | 
					 * @sband: the sband to search for the STA on
 | 
				
			||||||
 | 
					 * @iftype: enum nl80211_iftype
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: pointer to struct ieee80211_sband_iftype_data, or NULL is none found
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline const struct ieee80211_sband_iftype_data *
 | 
				
			||||||
 | 
					ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband,
 | 
				
			||||||
 | 
									u8 iftype)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (WARN_ON(iftype >= NL80211_IFTYPE_MAX))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < sband->n_iftype_data; i++)  {
 | 
				
			||||||
 | 
							const struct ieee80211_sband_iftype_data *data =
 | 
				
			||||||
 | 
								&sband->iftype_data[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (data->types_mask & BIT(iftype))
 | 
				
			||||||
 | 
								return data;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ieee80211_get_he_sta_cap - return HE capabilities for an sband's STA
 | 
				
			||||||
 | 
					 * @sband: the sband to search for the STA on
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: pointer to the struct ieee80211_sta_he_cap, or NULL is none found
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline const struct ieee80211_sta_he_cap *
 | 
				
			||||||
 | 
					ieee80211_get_he_sta_cap(const struct ieee80211_supported_band *sband)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct ieee80211_sband_iftype_data *data =
 | 
				
			||||||
 | 
							ieee80211_get_sband_iftype_data(sband, NL80211_IFTYPE_STATION);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (data && data->he_cap.has_he)
 | 
				
			||||||
 | 
							return &data->he_cap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * wiphy_read_of_freq_limits - read frequency limits from device tree
 | 
					 * wiphy_read_of_freq_limits - read frequency limits from device tree
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -899,6 +986,8 @@ enum station_parameters_apply_mask {
 | 
				
			||||||
 * @opmode_notif: operating mode field from Operating Mode Notification
 | 
					 * @opmode_notif: operating mode field from Operating Mode Notification
 | 
				
			||||||
 * @opmode_notif_used: information if operating mode field is used
 | 
					 * @opmode_notif_used: information if operating mode field is used
 | 
				
			||||||
 * @support_p2p_ps: information if station supports P2P PS mechanism
 | 
					 * @support_p2p_ps: information if station supports P2P PS mechanism
 | 
				
			||||||
 | 
					 * @he_capa: HE capabilities of station
 | 
				
			||||||
 | 
					 * @he_capa_len: the length of the HE capabilities
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct station_parameters {
 | 
					struct station_parameters {
 | 
				
			||||||
	const u8 *supported_rates;
 | 
						const u8 *supported_rates;
 | 
				
			||||||
| 
						 | 
					@ -926,6 +1015,8 @@ struct station_parameters {
 | 
				
			||||||
	u8 opmode_notif;
 | 
						u8 opmode_notif;
 | 
				
			||||||
	bool opmode_notif_used;
 | 
						bool opmode_notif_used;
 | 
				
			||||||
	int support_p2p_ps;
 | 
						int support_p2p_ps;
 | 
				
			||||||
 | 
						const struct ieee80211_he_cap_elem *he_capa;
 | 
				
			||||||
 | 
						u8 he_capa_len;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -1000,12 +1091,14 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
 | 
				
			||||||
 * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS
 | 
					 * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS
 | 
				
			||||||
 * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
 | 
					 * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
 | 
				
			||||||
 * @RATE_INFO_FLAGS_60G: 60GHz MCS
 | 
					 * @RATE_INFO_FLAGS_60G: 60GHz MCS
 | 
				
			||||||
 | 
					 * @RATE_INFO_FLAGS_HE_MCS: HE MCS information
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
enum rate_info_flags {
 | 
					enum rate_info_flags {
 | 
				
			||||||
	RATE_INFO_FLAGS_MCS			= BIT(0),
 | 
						RATE_INFO_FLAGS_MCS			= BIT(0),
 | 
				
			||||||
	RATE_INFO_FLAGS_VHT_MCS			= BIT(1),
 | 
						RATE_INFO_FLAGS_VHT_MCS			= BIT(1),
 | 
				
			||||||
	RATE_INFO_FLAGS_SHORT_GI		= BIT(2),
 | 
						RATE_INFO_FLAGS_SHORT_GI		= BIT(2),
 | 
				
			||||||
	RATE_INFO_FLAGS_60G			= BIT(3),
 | 
						RATE_INFO_FLAGS_60G			= BIT(3),
 | 
				
			||||||
 | 
						RATE_INFO_FLAGS_HE_MCS			= BIT(4),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -1019,6 +1112,7 @@ enum rate_info_flags {
 | 
				
			||||||
 * @RATE_INFO_BW_40: 40 MHz bandwidth
 | 
					 * @RATE_INFO_BW_40: 40 MHz bandwidth
 | 
				
			||||||
 * @RATE_INFO_BW_80: 80 MHz bandwidth
 | 
					 * @RATE_INFO_BW_80: 80 MHz bandwidth
 | 
				
			||||||
 * @RATE_INFO_BW_160: 160 MHz bandwidth
 | 
					 * @RATE_INFO_BW_160: 160 MHz bandwidth
 | 
				
			||||||
 | 
					 * @RATE_INFO_BW_HE_RU: bandwidth determined by HE RU allocation
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
enum rate_info_bw {
 | 
					enum rate_info_bw {
 | 
				
			||||||
	RATE_INFO_BW_20 = 0,
 | 
						RATE_INFO_BW_20 = 0,
 | 
				
			||||||
| 
						 | 
					@ -1027,6 +1121,7 @@ enum rate_info_bw {
 | 
				
			||||||
	RATE_INFO_BW_40,
 | 
						RATE_INFO_BW_40,
 | 
				
			||||||
	RATE_INFO_BW_80,
 | 
						RATE_INFO_BW_80,
 | 
				
			||||||
	RATE_INFO_BW_160,
 | 
						RATE_INFO_BW_160,
 | 
				
			||||||
 | 
						RATE_INFO_BW_HE_RU,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -1035,10 +1130,14 @@ enum rate_info_bw {
 | 
				
			||||||
 * Information about a receiving or transmitting bitrate
 | 
					 * Information about a receiving or transmitting bitrate
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @flags: bitflag of flags from &enum rate_info_flags
 | 
					 * @flags: bitflag of flags from &enum rate_info_flags
 | 
				
			||||||
 * @mcs: mcs index if struct describes a 802.11n bitrate
 | 
					 * @mcs: mcs index if struct describes an HT/VHT/HE rate
 | 
				
			||||||
 * @legacy: bitrate in 100kbit/s for 802.11abg
 | 
					 * @legacy: bitrate in 100kbit/s for 802.11abg
 | 
				
			||||||
 * @nss: number of streams (VHT only)
 | 
					 * @nss: number of streams (VHT & HE only)
 | 
				
			||||||
 * @bw: bandwidth (from &enum rate_info_bw)
 | 
					 * @bw: bandwidth (from &enum rate_info_bw)
 | 
				
			||||||
 | 
					 * @he_gi: HE guard interval (from &enum nl80211_he_gi)
 | 
				
			||||||
 | 
					 * @he_dcm: HE DCM value
 | 
				
			||||||
 | 
					 * @he_ru_alloc: HE RU allocation (from &enum nl80211_he_ru_alloc,
 | 
				
			||||||
 | 
					 *	only valid if bw is %RATE_INFO_BW_HE_RU)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct rate_info {
 | 
					struct rate_info {
 | 
				
			||||||
	u8 flags;
 | 
						u8 flags;
 | 
				
			||||||
| 
						 | 
					@ -1046,6 +1145,9 @@ struct rate_info {
 | 
				
			||||||
	u16 legacy;
 | 
						u16 legacy;
 | 
				
			||||||
	u8 nss;
 | 
						u8 nss;
 | 
				
			||||||
	u8 bw;
 | 
						u8 bw;
 | 
				
			||||||
 | 
						u8 he_gi;
 | 
				
			||||||
 | 
						u8 he_dcm;
 | 
				
			||||||
 | 
						u8 he_ru_alloc;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2237,6 +2237,9 @@ enum nl80211_commands {
 | 
				
			||||||
 *      enforced.
 | 
					 *      enforced.
 | 
				
			||||||
 * @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes
 | 
					 * @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes
 | 
				
			||||||
 *      a flow is assigned on each round of the DRR scheduler.
 | 
					 *      a flow is assigned on each round of the DRR scheduler.
 | 
				
			||||||
 | 
					 * @NL80211_ATTR_HE_CAPABILITY: HE Capability information element (from
 | 
				
			||||||
 | 
					 *	association request when used with NL80211_CMD_NEW_STATION). Can be set
 | 
				
			||||||
 | 
					 *	only if %NL80211_STA_FLAG_WME is set.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @NUM_NL80211_ATTR: total number of nl80211_attrs available
 | 
					 * @NUM_NL80211_ATTR: total number of nl80211_attrs available
 | 
				
			||||||
 * @NL80211_ATTR_MAX: highest attribute number currently defined
 | 
					 * @NL80211_ATTR_MAX: highest attribute number currently defined
 | 
				
			||||||
| 
						 | 
					@ -2677,6 +2680,8 @@ enum nl80211_attrs {
 | 
				
			||||||
	NL80211_ATTR_TXQ_MEMORY_LIMIT,
 | 
						NL80211_ATTR_TXQ_MEMORY_LIMIT,
 | 
				
			||||||
	NL80211_ATTR_TXQ_QUANTUM,
 | 
						NL80211_ATTR_TXQ_QUANTUM,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL80211_ATTR_HE_CAPABILITY,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* add attributes here, update the policy in nl80211.c */
 | 
						/* add attributes here, update the policy in nl80211.c */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	__NL80211_ATTR_AFTER_LAST,
 | 
						__NL80211_ATTR_AFTER_LAST,
 | 
				
			||||||
| 
						 | 
					@ -2726,7 +2731,8 @@ enum nl80211_attrs {
 | 
				
			||||||
#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY	24
 | 
					#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY	24
 | 
				
			||||||
#define NL80211_HT_CAPABILITY_LEN		26
 | 
					#define NL80211_HT_CAPABILITY_LEN		26
 | 
				
			||||||
#define NL80211_VHT_CAPABILITY_LEN		12
 | 
					#define NL80211_VHT_CAPABILITY_LEN		12
 | 
				
			||||||
 | 
					#define NL80211_HE_MIN_CAPABILITY_LEN           16
 | 
				
			||||||
 | 
					#define NL80211_HE_MAX_CAPABILITY_LEN           51
 | 
				
			||||||
#define NL80211_MAX_NR_CIPHER_SUITES		5
 | 
					#define NL80211_MAX_NR_CIPHER_SUITES		5
 | 
				
			||||||
#define NL80211_MAX_NR_AKM_SUITES		2
 | 
					#define NL80211_MAX_NR_AKM_SUITES		2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2853,6 +2859,38 @@ struct nl80211_sta_flag_update {
 | 
				
			||||||
	__u32 set;
 | 
						__u32 set;
 | 
				
			||||||
} __attribute__((packed));
 | 
					} __attribute__((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * enum nl80211_he_gi - HE guard interval
 | 
				
			||||||
 | 
					 * @NL80211_RATE_INFO_HE_GI_0_8: 0.8 usec
 | 
				
			||||||
 | 
					 * @NL80211_RATE_INFO_HE_GI_1_6: 1.6 usec
 | 
				
			||||||
 | 
					 * @NL80211_RATE_INFO_HE_GI_3_2: 3.2 usec
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum nl80211_he_gi {
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_GI_0_8,
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_GI_1_6,
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_GI_3_2,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * enum nl80211_he_ru_alloc - HE RU allocation values
 | 
				
			||||||
 | 
					 * @NL80211_RATE_INFO_HE_RU_ALLOC_26: 26-tone RU allocation
 | 
				
			||||||
 | 
					 * @NL80211_RATE_INFO_HE_RU_ALLOC_52: 52-tone RU allocation
 | 
				
			||||||
 | 
					 * @NL80211_RATE_INFO_HE_RU_ALLOC_106: 106-tone RU allocation
 | 
				
			||||||
 | 
					 * @NL80211_RATE_INFO_HE_RU_ALLOC_242: 242-tone RU allocation
 | 
				
			||||||
 | 
					 * @NL80211_RATE_INFO_HE_RU_ALLOC_484: 484-tone RU allocation
 | 
				
			||||||
 | 
					 * @NL80211_RATE_INFO_HE_RU_ALLOC_996: 996-tone RU allocation
 | 
				
			||||||
 | 
					 * @NL80211_RATE_INFO_HE_RU_ALLOC_2x996: 2x996-tone RU allocation
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum nl80211_he_ru_alloc {
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_RU_ALLOC_26,
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_RU_ALLOC_52,
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_RU_ALLOC_106,
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_RU_ALLOC_242,
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_RU_ALLOC_484,
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_RU_ALLOC_996,
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_RU_ALLOC_2x996,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * enum nl80211_rate_info - bitrate information
 | 
					 * enum nl80211_rate_info - bitrate information
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -2885,6 +2923,13 @@ struct nl80211_sta_flag_update {
 | 
				
			||||||
 * @NL80211_RATE_INFO_5_MHZ_WIDTH: 5 MHz width - note that this is
 | 
					 * @NL80211_RATE_INFO_5_MHZ_WIDTH: 5 MHz width - note that this is
 | 
				
			||||||
 *	a legacy rate and will be reported as the actual bitrate, i.e.
 | 
					 *	a legacy rate and will be reported as the actual bitrate, i.e.
 | 
				
			||||||
 *	a quarter of the base (20 MHz) rate
 | 
					 *	a quarter of the base (20 MHz) rate
 | 
				
			||||||
 | 
					 * @NL80211_RATE_INFO_HE_MCS: HE MCS index (u8, 0-11)
 | 
				
			||||||
 | 
					 * @NL80211_RATE_INFO_HE_NSS: HE NSS value (u8, 1-8)
 | 
				
			||||||
 | 
					 * @NL80211_RATE_INFO_HE_GI: HE guard interval identifier
 | 
				
			||||||
 | 
					 *	(u8, see &enum nl80211_he_gi)
 | 
				
			||||||
 | 
					 * @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_AFTER_LAST: internal use
 | 
					 * @__NL80211_RATE_INFO_AFTER_LAST: internal use
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
enum nl80211_rate_info {
 | 
					enum nl80211_rate_info {
 | 
				
			||||||
| 
						 | 
					@ -2901,6 +2946,11 @@ enum nl80211_rate_info {
 | 
				
			||||||
	NL80211_RATE_INFO_160_MHZ_WIDTH,
 | 
						NL80211_RATE_INFO_160_MHZ_WIDTH,
 | 
				
			||||||
	NL80211_RATE_INFO_10_MHZ_WIDTH,
 | 
						NL80211_RATE_INFO_10_MHZ_WIDTH,
 | 
				
			||||||
	NL80211_RATE_INFO_5_MHZ_WIDTH,
 | 
						NL80211_RATE_INFO_5_MHZ_WIDTH,
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_MCS,
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_NSS,
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_GI,
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_DCM,
 | 
				
			||||||
 | 
						NL80211_RATE_INFO_HE_RU_ALLOC,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* keep last */
 | 
						/* keep last */
 | 
				
			||||||
	__NL80211_RATE_INFO_AFTER_LAST,
 | 
						__NL80211_RATE_INFO_AFTER_LAST,
 | 
				
			||||||
| 
						 | 
					@ -3166,6 +3216,38 @@ enum nl80211_mpath_info {
 | 
				
			||||||
	NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1
 | 
						NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * enum nl80211_band_iftype_attr - Interface type data attributes
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @__NL80211_BAND_IFTYPE_ATTR_INVALID: attribute number 0 is reserved
 | 
				
			||||||
 | 
					 * @NL80211_BAND_IFTYPE_ATTR_IFTYPES: nested attribute containing a flag attribute
 | 
				
			||||||
 | 
					 *     for each interface type that supports the band data
 | 
				
			||||||
 | 
					 * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC: HE MAC capabilities as in HE
 | 
				
			||||||
 | 
					 *     capabilities IE
 | 
				
			||||||
 | 
					 * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY: HE PHY capabilities as in HE
 | 
				
			||||||
 | 
					 *     capabilities IE
 | 
				
			||||||
 | 
					 * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET: HE supported NSS/MCS as in HE
 | 
				
			||||||
 | 
					 *     capabilities IE
 | 
				
			||||||
 | 
					 * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE: HE PPE thresholds information as
 | 
				
			||||||
 | 
					 *     defined in HE capabilities IE
 | 
				
			||||||
 | 
					 * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band HE capability attribute currently
 | 
				
			||||||
 | 
					 *     defined
 | 
				
			||||||
 | 
					 * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum nl80211_band_iftype_attr {
 | 
				
			||||||
 | 
						__NL80211_BAND_IFTYPE_ATTR_INVALID,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL80211_BAND_IFTYPE_ATTR_IFTYPES,
 | 
				
			||||||
 | 
						NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC,
 | 
				
			||||||
 | 
						NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
 | 
				
			||||||
 | 
						NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
 | 
				
			||||||
 | 
						NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* keep last */
 | 
				
			||||||
 | 
						__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST,
 | 
				
			||||||
 | 
						NL80211_BAND_IFTYPE_ATTR_MAX = __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST - 1
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * enum nl80211_band_attr - band attributes
 | 
					 * enum nl80211_band_attr - band attributes
 | 
				
			||||||
 * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved
 | 
					 * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved
 | 
				
			||||||
| 
						 | 
					@ -3181,6 +3263,8 @@ enum nl80211_mpath_info {
 | 
				
			||||||
 * @NL80211_BAND_ATTR_VHT_MCS_SET: 32-byte attribute containing the MCS set as
 | 
					 * @NL80211_BAND_ATTR_VHT_MCS_SET: 32-byte attribute containing the MCS set as
 | 
				
			||||||
 *	defined in 802.11ac
 | 
					 *	defined in 802.11ac
 | 
				
			||||||
 * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE
 | 
					 * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE
 | 
				
			||||||
 | 
					 * @NL80211_BAND_ATTR_IFTYPE_DATA: nested array attribute, with each entry using
 | 
				
			||||||
 | 
					 *	attributes from &enum nl80211_band_iftype_attr
 | 
				
			||||||
 * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
 | 
					 * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
 | 
				
			||||||
 * @__NL80211_BAND_ATTR_AFTER_LAST: internal use
 | 
					 * @__NL80211_BAND_ATTR_AFTER_LAST: internal use
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -3196,6 +3280,7 @@ enum nl80211_band_attr {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	NL80211_BAND_ATTR_VHT_MCS_SET,
 | 
						NL80211_BAND_ATTR_VHT_MCS_SET,
 | 
				
			||||||
	NL80211_BAND_ATTR_VHT_CAPA,
 | 
						NL80211_BAND_ATTR_VHT_CAPA,
 | 
				
			||||||
 | 
						NL80211_BAND_ATTR_IFTYPE_DATA,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* keep last */
 | 
						/* keep last */
 | 
				
			||||||
	__NL80211_BAND_ATTR_AFTER_LAST,
 | 
						__NL80211_BAND_ATTR_AFTER_LAST,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Copyright 2006-2010		Johannes Berg <johannes@sipsolutions.net>
 | 
					 * Copyright 2006-2010		Johannes Berg <johannes@sipsolutions.net>
 | 
				
			||||||
 * Copyright 2013-2014  Intel Mobile Communications GmbH
 | 
					 * Copyright 2013-2014  Intel Mobile Communications GmbH
 | 
				
			||||||
 * Copyright 2015	Intel Deutschland GmbH
 | 
					 * Copyright 2015-2017	Intel Deutschland GmbH
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 | 
					#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 | 
				
			||||||
| 
						 | 
					@ -744,6 +744,8 @@ int wiphy_register(struct wiphy *wiphy)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* sanity check supported bands/channels */
 | 
						/* sanity check supported bands/channels */
 | 
				
			||||||
	for (band = 0; band < NUM_NL80211_BANDS; band++) {
 | 
						for (band = 0; band < NUM_NL80211_BANDS; band++) {
 | 
				
			||||||
 | 
							u16 types = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		sband = wiphy->bands[band];
 | 
							sband = wiphy->bands[band];
 | 
				
			||||||
		if (!sband)
 | 
							if (!sband)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
| 
						 | 
					@ -788,6 +790,23 @@ int wiphy_register(struct wiphy *wiphy)
 | 
				
			||||||
			sband->channels[i].band = band;
 | 
								sband->channels[i].band = band;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (i = 0; i < sband->n_iftype_data; i++) {
 | 
				
			||||||
 | 
								const struct ieee80211_sband_iftype_data *iftd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								iftd = &sband->iftype_data[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (WARN_ON(!iftd->types_mask))
 | 
				
			||||||
 | 
									return -EINVAL;
 | 
				
			||||||
 | 
								if (WARN_ON(types & iftd->types_mask))
 | 
				
			||||||
 | 
									return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* at least one piece of information must be present */
 | 
				
			||||||
 | 
								if (WARN_ON(!iftd->he_cap.has_he))
 | 
				
			||||||
 | 
									return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								types |= iftd->types_mask;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		have_band = true;
 | 
							have_band = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -428,6 +428,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
 | 
				
			||||||
	[NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
 | 
						[NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
 | 
				
			||||||
	[NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
 | 
						[NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
 | 
				
			||||||
	[NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
 | 
						[NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
 | 
				
			||||||
 | 
						[NL80211_ATTR_HE_CAPABILITY] = { .type = NLA_BINARY,
 | 
				
			||||||
 | 
										 .len = NL80211_HE_MAX_CAPABILITY_LEN },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* policy for the key attributes */
 | 
					/* policy for the key attributes */
 | 
				
			||||||
| 
						 | 
					@ -1324,6 +1326,34 @@ static int nl80211_send_coalesce(struct sk_buff *msg,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES,
 | 
				
			||||||
 | 
									iftdata->types_mask))
 | 
				
			||||||
 | 
							return -ENOBUFS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (he_cap->has_he) {
 | 
				
			||||||
 | 
							if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC,
 | 
				
			||||||
 | 
								    sizeof(he_cap->he_cap_elem.mac_cap_info),
 | 
				
			||||||
 | 
								    he_cap->he_cap_elem.mac_cap_info) ||
 | 
				
			||||||
 | 
							    nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
 | 
				
			||||||
 | 
								    sizeof(he_cap->he_cap_elem.phy_cap_info),
 | 
				
			||||||
 | 
								    he_cap->he_cap_elem.phy_cap_info) ||
 | 
				
			||||||
 | 
							    nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
 | 
				
			||||||
 | 
								    sizeof(he_cap->he_mcs_nss_supp),
 | 
				
			||||||
 | 
								    &he_cap->he_mcs_nss_supp) ||
 | 
				
			||||||
 | 
							    nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
 | 
				
			||||||
 | 
								    sizeof(he_cap->ppe_thres), he_cap->ppe_thres))
 | 
				
			||||||
 | 
								return -ENOBUFS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int nl80211_send_band_rateinfo(struct sk_buff *msg,
 | 
					static int nl80211_send_band_rateinfo(struct sk_buff *msg,
 | 
				
			||||||
				      struct ieee80211_supported_band *sband)
 | 
									      struct ieee80211_supported_band *sband)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1353,6 +1383,32 @@ static int nl80211_send_band_rateinfo(struct sk_buff *msg,
 | 
				
			||||||
			 sband->vht_cap.cap)))
 | 
								 sband->vht_cap.cap)))
 | 
				
			||||||
		return -ENOBUFS;
 | 
							return -ENOBUFS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sband->n_iftype_data) {
 | 
				
			||||||
 | 
							struct nlattr *nl_iftype_data =
 | 
				
			||||||
 | 
								nla_nest_start(msg, NL80211_BAND_ATTR_IFTYPE_DATA);
 | 
				
			||||||
 | 
							int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!nl_iftype_data)
 | 
				
			||||||
 | 
								return -ENOBUFS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (i = 0; i < sband->n_iftype_data; i++) {
 | 
				
			||||||
 | 
								struct nlattr *iftdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								iftdata = nla_nest_start(msg, i + 1);
 | 
				
			||||||
 | 
								if (!iftdata)
 | 
				
			||||||
 | 
									return -ENOBUFS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								err = nl80211_send_iftype_data(msg,
 | 
				
			||||||
 | 
											       &sband->iftype_data[i]);
 | 
				
			||||||
 | 
								if (err)
 | 
				
			||||||
 | 
									return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								nla_nest_end(msg, iftdata);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							nla_nest_end(msg, nl_iftype_data);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* add bitrates */
 | 
						/* add bitrates */
 | 
				
			||||||
	nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
 | 
						nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
 | 
				
			||||||
	if (!nl_rates)
 | 
						if (!nl_rates)
 | 
				
			||||||
| 
						 | 
					@ -4472,6 +4528,9 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
 | 
				
			||||||
	case RATE_INFO_BW_160:
 | 
						case RATE_INFO_BW_160:
 | 
				
			||||||
		rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH;
 | 
							rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case RATE_INFO_BW_HE_RU:
 | 
				
			||||||
 | 
							rate_flg = 0;
 | 
				
			||||||
 | 
							WARN_ON(!(info->flags & RATE_INFO_FLAGS_HE_MCS));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (rate_flg && nla_put_flag(msg, rate_flg))
 | 
						if (rate_flg && nla_put_flag(msg, rate_flg))
 | 
				
			||||||
| 
						 | 
					@ -4491,6 +4550,19 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
 | 
				
			||||||
		if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
 | 
							if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
 | 
				
			||||||
		    nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
 | 
							    nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
 | 
						} else if (info->flags & RATE_INFO_FLAGS_HE_MCS) {
 | 
				
			||||||
 | 
							if (nla_put_u8(msg, NL80211_RATE_INFO_HE_MCS, info->mcs))
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							if (nla_put_u8(msg, NL80211_RATE_INFO_HE_NSS, info->nss))
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							if (nla_put_u8(msg, NL80211_RATE_INFO_HE_GI, info->he_gi))
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							if (nla_put_u8(msg, NL80211_RATE_INFO_HE_DCM, info->he_dcm))
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							if (info->bw == RATE_INFO_BW_HE_RU &&
 | 
				
			||||||
 | 
							    nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
 | 
				
			||||||
 | 
								       info->he_ru_alloc))
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nla_nest_end(msg, rate);
 | 
						nla_nest_end(msg, rate);
 | 
				
			||||||
| 
						 | 
					@ -4887,7 +4959,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
		if (params->supported_rates)
 | 
							if (params->supported_rates)
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
		if (params->ext_capab || params->ht_capa || params->vht_capa)
 | 
							if (params->ext_capab || params->ht_capa || params->vht_capa ||
 | 
				
			||||||
 | 
							    params->he_capa)
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5093,6 +5166,15 @@ static int nl80211_set_station_tdls(struct genl_info *info,
 | 
				
			||||||
	if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
 | 
						if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
 | 
				
			||||||
		params->vht_capa =
 | 
							params->vht_capa =
 | 
				
			||||||
			nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
 | 
								nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
 | 
				
			||||||
 | 
						if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
 | 
				
			||||||
 | 
							params->he_capa =
 | 
				
			||||||
 | 
								nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
 | 
				
			||||||
 | 
							params->he_capa_len =
 | 
				
			||||||
 | 
								nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (params->he_capa_len < NL80211_HE_MIN_CAPABILITY_LEN)
 | 
				
			||||||
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = nl80211_parse_sta_channel_info(info, params);
 | 
						err = nl80211_parse_sta_channel_info(info, params);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
| 
						 | 
					@ -5320,6 +5402,17 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
		params.vht_capa =
 | 
							params.vht_capa =
 | 
				
			||||||
			nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
 | 
								nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->attrs[NL80211_ATTR_HE_CAPABILITY]) {
 | 
				
			||||||
 | 
							params.he_capa =
 | 
				
			||||||
 | 
								nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
 | 
				
			||||||
 | 
							params.he_capa_len =
 | 
				
			||||||
 | 
								nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* max len is validated in nla policy */
 | 
				
			||||||
 | 
							if (params.he_capa_len < NL80211_HE_MIN_CAPABILITY_LEN)
 | 
				
			||||||
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
 | 
						if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
 | 
				
			||||||
		params.opmode_notif_used = true;
 | 
							params.opmode_notif_used = true;
 | 
				
			||||||
		params.opmode_notif =
 | 
							params.opmode_notif =
 | 
				
			||||||
| 
						 | 
					@ -5352,6 +5445,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
	if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
 | 
						if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
 | 
				
			||||||
		params.ht_capa = NULL;
 | 
							params.ht_capa = NULL;
 | 
				
			||||||
		params.vht_capa = NULL;
 | 
							params.vht_capa = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* HE requires WME */
 | 
				
			||||||
 | 
							if (params.he_capa_len)
 | 
				
			||||||
 | 
								return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* When you run into this, adjust the code below for the new flag */
 | 
						/* When you run into this, adjust the code below for the new flag */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Copyright 2007-2009	Johannes Berg <johannes@sipsolutions.net>
 | 
					 * Copyright 2007-2009	Johannes Berg <johannes@sipsolutions.net>
 | 
				
			||||||
 * Copyright 2013-2014  Intel Mobile Communications GmbH
 | 
					 * Copyright 2013-2014  Intel Mobile Communications GmbH
 | 
				
			||||||
 | 
					 * Copyright 2017	Intel Deutschland GmbH
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#include <linux/export.h>
 | 
					#include <linux/export.h>
 | 
				
			||||||
#include <linux/bitops.h>
 | 
					#include <linux/bitops.h>
 | 
				
			||||||
| 
						 | 
					@ -1142,6 +1143,85 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#define SCALE 2048
 | 
				
			||||||
 | 
						u16 mcs_divisors[12] = {
 | 
				
			||||||
 | 
							34133, /* 16.666666... */
 | 
				
			||||||
 | 
							17067, /*  8.333333... */
 | 
				
			||||||
 | 
							11378, /*  5.555555... */
 | 
				
			||||||
 | 
							 8533, /*  4.166666... */
 | 
				
			||||||
 | 
							 5689, /*  2.777777... */
 | 
				
			||||||
 | 
							 4267, /*  2.083333... */
 | 
				
			||||||
 | 
							 3923, /*  1.851851... */
 | 
				
			||||||
 | 
							 3413, /*  1.666666... */
 | 
				
			||||||
 | 
							 2844, /*  1.388888... */
 | 
				
			||||||
 | 
							 2560, /*  1.250000... */
 | 
				
			||||||
 | 
							 2276, /*  1.111111... */
 | 
				
			||||||
 | 
							 2048, /*  1.000000... */
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						u32 rates_160M[3] = { 960777777, 907400000, 816666666 };
 | 
				
			||||||
 | 
						u32 rates_969[3] =  { 480388888, 453700000, 408333333 };
 | 
				
			||||||
 | 
						u32 rates_484[3] =  { 229411111, 216666666, 195000000 };
 | 
				
			||||||
 | 
						u32 rates_242[3] =  { 114711111, 108333333,  97500000 };
 | 
				
			||||||
 | 
						u32 rates_106[3] =  {  40000000,  37777777,  34000000 };
 | 
				
			||||||
 | 
						u32 rates_52[3]  =  {  18820000,  17777777,  16000000 };
 | 
				
			||||||
 | 
						u32 rates_26[3]  =  {   9411111,   8888888,   8000000 };
 | 
				
			||||||
 | 
						u64 tmp;
 | 
				
			||||||
 | 
						u32 result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (WARN_ON_ONCE(rate->mcs > 11))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (WARN_ON_ONCE(rate->he_gi > NL80211_RATE_INFO_HE_GI_3_2))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						if (WARN_ON_ONCE(rate->he_ru_alloc >
 | 
				
			||||||
 | 
								 NL80211_RATE_INFO_HE_RU_ALLOC_2x996))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						if (WARN_ON_ONCE(rate->nss < 1 || rate->nss > 8))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rate->bw == RATE_INFO_BW_160)
 | 
				
			||||||
 | 
							result = rates_160M[rate->he_gi];
 | 
				
			||||||
 | 
						else if (rate->bw == RATE_INFO_BW_80 ||
 | 
				
			||||||
 | 
							 (rate->bw == RATE_INFO_BW_HE_RU &&
 | 
				
			||||||
 | 
							  rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_996))
 | 
				
			||||||
 | 
							result = rates_969[rate->he_gi];
 | 
				
			||||||
 | 
						else if (rate->bw == RATE_INFO_BW_40 ||
 | 
				
			||||||
 | 
							 (rate->bw == RATE_INFO_BW_HE_RU &&
 | 
				
			||||||
 | 
							  rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_484))
 | 
				
			||||||
 | 
							result = rates_484[rate->he_gi];
 | 
				
			||||||
 | 
						else if (rate->bw == RATE_INFO_BW_20 ||
 | 
				
			||||||
 | 
							 (rate->bw == RATE_INFO_BW_HE_RU &&
 | 
				
			||||||
 | 
							  rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_242))
 | 
				
			||||||
 | 
							result = rates_242[rate->he_gi];
 | 
				
			||||||
 | 
						else if (rate->bw == RATE_INFO_BW_HE_RU &&
 | 
				
			||||||
 | 
							 rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_106)
 | 
				
			||||||
 | 
							result = rates_106[rate->he_gi];
 | 
				
			||||||
 | 
						else if (rate->bw == RATE_INFO_BW_HE_RU &&
 | 
				
			||||||
 | 
							 rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_52)
 | 
				
			||||||
 | 
							result = rates_52[rate->he_gi];
 | 
				
			||||||
 | 
						else if (rate->bw == RATE_INFO_BW_HE_RU &&
 | 
				
			||||||
 | 
							 rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_26)
 | 
				
			||||||
 | 
							result = rates_26[rate->he_gi];
 | 
				
			||||||
 | 
						else if (WARN(1, "invalid HE MCS: bw:%d, ru:%d\n",
 | 
				
			||||||
 | 
							      rate->bw, rate->he_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, DCM into account */
 | 
				
			||||||
 | 
						result = (result * rate->nss) / 8;
 | 
				
			||||||
 | 
						if (rate->he_dcm)
 | 
				
			||||||
 | 
							result /= 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
u32 cfg80211_calculate_bitrate(struct rate_info *rate)
 | 
					u32 cfg80211_calculate_bitrate(struct rate_info *rate)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (rate->flags & RATE_INFO_FLAGS_MCS)
 | 
						if (rate->flags & RATE_INFO_FLAGS_MCS)
 | 
				
			||||||
| 
						 | 
					@ -1150,6 +1230,8 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate)
 | 
				
			||||||
		return cfg80211_calculate_bitrate_60g(rate);
 | 
							return cfg80211_calculate_bitrate_60g(rate);
 | 
				
			||||||
	if (rate->flags & RATE_INFO_FLAGS_VHT_MCS)
 | 
						if (rate->flags & RATE_INFO_FLAGS_VHT_MCS)
 | 
				
			||||||
		return cfg80211_calculate_bitrate_vht(rate);
 | 
							return cfg80211_calculate_bitrate_vht(rate);
 | 
				
			||||||
 | 
						if (rate->flags & RATE_INFO_FLAGS_HE_MCS)
 | 
				
			||||||
 | 
							return cfg80211_calculate_bitrate_he(rate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return rate->legacy;
 | 
						return rate->legacy;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue