Commit a11ec0dc authored by Somashekhar Puttagangaiah's avatar Somashekhar Puttagangaiah Committed by Johannes Berg
Browse files

wifi: cfg80211/mac80211: implement dot11ExtendedRegInfoSupport



Implement dot11ExtendedRegInfoSupport to advertise non-AP station
regulatory power capability as part of regulatory connectivity
element in (Re)Association request frames so that AP can achieve
maximum client connectivity. Control field which was interpreted
using value of 3-bits B5 to B3, now uses value of 4-bits B6 to B3 to
interpret the type of AP. Hence update IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO
to parse 4-bits control field. If older AP still updates only 3-bits
value of control field, station can still interpret the value as per
section E.2.7 of IEEE 802.11 REVme D7.0 and support the appropriate
AP type.

Also update IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP as the value of
standard power AP is changed to 8 instead of 4 so that AP can support both
LPI AP and SP AP to maximize the connectivity with stations. For backward
compatibility, keeping value 4 as old AP by limiting it to SP AP only.

Signed-off-by: default avatarSomashekhar Puttagangaiah <somashekhar.puttagangaiah@intel.com>
Reviewed-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250609213232.90cdef116aad.I85da390fbee59355e3855691933e6a5e55c47ac4@changeid


[fix kernel-doc]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent a9681efa
Loading
Loading
Loading
Loading
+28 −6
Original line number Diff line number Diff line
@@ -2841,7 +2841,8 @@ static inline bool ieee80211_he_capa_size_ok(const u8 *data, u8 len)
#define IEEE80211_6GHZ_CTRL_REG_SP_AP			1
#define IEEE80211_6GHZ_CTRL_REG_VLP_AP			2
#define IEEE80211_6GHZ_CTRL_REG_INDOOR_LPI_AP		3
#define IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP	4
#define IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP_OLD	4
#define IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP		8

/**
 * struct ieee80211_he_6ghz_oper - HE 6 GHz operation Information field
@@ -2859,13 +2860,31 @@ struct ieee80211_he_6ghz_oper {
#define		IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ	2
#define		IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ	3
#define IEEE80211_HE_6GHZ_OPER_CTRL_DUP_BEACON	0x4
#define IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO	0x38
#define IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO	0x78
	u8 control;
	u8 ccfs0;
	u8 ccfs1;
	u8 minrate;
} __packed;

/**
 * enum ieee80211_reg_conn_bits - represents Regulatory connectivity field bits.
 *
 * This enumeration defines bit flags used to represent regulatory connectivity
 * field bits.
 *
 * @IEEE80211_REG_CONN_LPI_VALID: Indicates whether the LPI bit is valid.
 * @IEEE80211_REG_CONN_LPI_VALUE: Represents the value of the LPI bit.
 * @IEEE80211_REG_CONN_SP_VALID: Indicates whether the SP bit is valid.
 * @IEEE80211_REG_CONN_SP_VALUE: Represents the value of the SP bit.
 */
enum ieee80211_reg_conn_bits {
	IEEE80211_REG_CONN_LPI_VALID = BIT(0),
	IEEE80211_REG_CONN_LPI_VALUE = BIT(1),
	IEEE80211_REG_CONN_SP_VALID = BIT(2),
	IEEE80211_REG_CONN_SP_VALUE = BIT(3),
};

/* transmit power interpretation type of transmit power envelope element */
enum ieee80211_tx_power_intrpt_type {
	IEEE80211_TPE_LOCAL_EIRP,
@@ -3847,6 +3866,7 @@ enum ieee80211_eid_ext {
	WLAN_EID_EXT_FILS_PUBLIC_KEY = 12,
	WLAN_EID_EXT_FILS_NONCE = 13,
	WLAN_EID_EXT_FUTURE_CHAN_GUIDANCE = 14,
	WLAN_EID_EXT_DH_PARAMETER = 32,
	WLAN_EID_EXT_HE_CAPABILITY = 35,
	WLAN_EID_EXT_HE_OPERATION = 36,
	WLAN_EID_EXT_UORA = 37,
@@ -3870,6 +3890,8 @@ enum ieee80211_eid_ext {
	WLAN_EID_EXT_EHT_CAPABILITY = 108,
	WLAN_EID_EXT_TID_TO_LINK_MAPPING = 109,
	WLAN_EID_EXT_BANDWIDTH_INDICATION = 135,
	WLAN_EID_EXT_KNOWN_STA_IDENTIFCATION = 136,
	WLAN_EID_EXT_NON_AP_STA_REG_CON = 137,
};

/* Action category code */
+2 −0
Original line number Diff line number Diff line
@@ -2642,6 +2642,8 @@ int ieee80211_put_eht_cap(struct sk_buff *skb,
			  struct ieee80211_sub_if_data *sdata,
			  const struct ieee80211_supported_band *sband,
			  const struct ieee80211_conn_settings *conn);
int ieee80211_put_reg_conn(struct sk_buff *skb,
			   enum ieee80211_channel_flags flags);

/* channel management */
bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
+41 −0
Original line number Diff line number Diff line
@@ -1641,6 +1641,30 @@ static size_t ieee80211_add_before_he_elems(struct sk_buff *skb,
	return noffset;
}

static size_t ieee80211_add_before_reg_conn(struct sk_buff *skb,
					    const u8 *elems, size_t elems_len,
					    size_t offset)
{
	static const u8 before_reg_conn[] = {
		/*
		 * no need to list the ones split off before HE
		 * or generated here
		 */
		WLAN_EID_EXTENSION, WLAN_EID_EXT_DH_PARAMETER,
		WLAN_EID_EXTENSION, WLAN_EID_EXT_KNOWN_STA_IDENTIFCATION,
	};
	size_t noffset;

	if (!elems_len)
		return offset;

	noffset = ieee80211_ie_split(elems, elems_len, before_reg_conn,
				     ARRAY_SIZE(before_reg_conn), offset);
	skb_put_data(skb, elems + offset, noffset - offset);

	return noffset;
}

#define PRESENT_ELEMS_MAX	8
#define PRESENT_ELEM_EXT_OFFS	0x100

@@ -1801,6 +1825,22 @@ ieee80211_add_link_elems(struct ieee80211_sub_if_data *sdata,
		ieee80211_put_he_6ghz_cap(skb, sdata, smps_mode);
	}

	/*
	 * if present, add any custom IEs that go before regulatory
	 * connectivity element
	 */
	offset = ieee80211_add_before_reg_conn(skb, extra_elems,
					       extra_elems_len, offset);

	if (sband->band == NL80211_BAND_6GHZ) {
		/*
		 * as per Section E.2.7 of IEEE 802.11 REVme D7.0, non-AP STA
		 * capable of operating on the 6 GHz band shall transmit
		 * regulatory connectivity element.
		 */
		ieee80211_put_reg_conn(skb, chan->flags);
	}

	/*
	 * careful - need to know about all the present elems before
	 * calling ieee80211_assoc_add_ml_elem(), so add this one if
@@ -5931,6 +5971,7 @@ ieee80211_ap_power_type(u8 control)
		return IEEE80211_REG_LPI_AP;
	case IEEE80211_6GHZ_CTRL_REG_SP_AP:
	case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP:
	case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP_OLD:
		return IEEE80211_REG_SP_AP;
	case IEEE80211_6GHZ_CTRL_REG_VLP_AP:
		return IEEE80211_REG_VLP_AP;
+17 −0
Original line number Diff line number Diff line
@@ -2556,6 +2556,23 @@ int ieee80211_put_he_cap(struct sk_buff *skb,
	return 0;
}

int ieee80211_put_reg_conn(struct sk_buff *skb,
			   enum ieee80211_channel_flags flags)
{
	u8 reg_conn = IEEE80211_REG_CONN_LPI_VALID |
		      IEEE80211_REG_CONN_LPI_VALUE |
		      IEEE80211_REG_CONN_SP_VALID;

	if (!(flags & IEEE80211_CHAN_NO_6GHZ_AFC_CLIENT))
		reg_conn |= IEEE80211_REG_CONN_SP_VALUE;

	skb_put_u8(skb, WLAN_EID_EXTENSION);
	skb_put_u8(skb, 1 + sizeof(reg_conn));
	skb_put_u8(skb, WLAN_EID_EXT_NON_AP_STA_REG_CON);
	skb_put_u8(skb, reg_conn);
	return 0;
}

int ieee80211_put_he_6ghz_cap(struct sk_buff *skb,
			      struct ieee80211_sub_if_data *sdata,
			      enum ieee80211_smps_mode smps_mode)
+1 −0
Original line number Diff line number Diff line
@@ -2231,6 +2231,7 @@ cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len)
		return IEEE80211_REG_LPI_AP;
	case IEEE80211_6GHZ_CTRL_REG_SP_AP:
	case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP:
	case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP_OLD:
		return IEEE80211_REG_SP_AP;
	case IEEE80211_6GHZ_CTRL_REG_VLP_AP:
		return IEEE80211_REG_VLP_AP;