Commit 1e0b3b0b authored by Ilan Peer's avatar Ilan Peer Committed by Johannes Berg
Browse files

wifi: mac80211: Align with Draft P802.11be_D1.5



Align the mac80211 implementation with P802.11be_D1.5.

Signed-off-by: default avatarIlan Peer <ilan.peer@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 28977e79
Loading
Loading
Loading
Loading
+36 −16
Original line number Diff line number Diff line
@@ -2046,25 +2046,38 @@ struct ieee80211_eht_cap_elem {
	u8 optional[];
} __packed;

#define IEEE80211_EHT_OPER_INFO_PRESENT	                        0x1
#define IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT	0x2

/**
 * struct ieee80211_eht_operation - eht operation element
 *
 * This structure is the "EHT Operation Element" fields as
 * described in P802.11be_D1.4 section 9.4.2.311
 * described in P802.11be_D1.5 section 9.4.2.311
 *
 * FIXME: The spec is unclear how big the fields are, and doesn't
 *	  indicate the "Disabled Subchannel Bitmap Present" in the
 *	  structure (Figure 9-1002a) at all ...
 * @params: EHT operation element parameters. See &IEEE80211_EHT_OPER_*
 * @optional: optional parts
 */
struct ieee80211_eht_operation {
	u8 chan_width;
	u8 ccfs;
	u8 present_bm;

	u8 disable_subchannel_bitmap[];
	u8 params;
	u8 optional[];
} __packed;

#define IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT	0x1
/**
 * struct ieee80211_eht_operation_info - eht operation information
 *
 * @control: EHT operation information control.
 * @ccfs0: defines a channel center frequency for a 20, 40, 80, 160, or 320 MHz
 *     EHT BSS.
 * @ccfs1: defines a channel center frequency for a 160 or 320 MHz EHT BSS.
 * @optional: optional parts
 */
struct ieee80211_eht_operation_info {
	u8 control;
	u8 ccfs0;
	u8 ccfs1;
	u8 optional[];
} __packed;

/* 802.11ac VHT Capabilities */
#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895			0x00000000
@@ -2773,10 +2786,12 @@ ieee80211_he_spr_size(const u8 *he_spr_ie)
#define IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2		0x08
#define IEEE80211_EHT_MAC_CAP0_RESTRICTED_TWT			0x10
#define IEEE80211_EHT_MAC_CAP0_SCS_TRAFFIC_DESC			0x20
#define IEEE80211_EHT_MAC_CAP0_MAX_AMPDU_LEN_MASK		0xc0
#define		IEEE80211_EHT_MAC_CAP0_MAX_AMPDU_LEN_3895	0
#define		IEEE80211_EHT_MAC_CAP0_MAX_AMPDU_LEN_7991	1
#define		IEEE80211_EHT_MAC_CAP0_MAX_AMPDU_LEN_11454	2
#define IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK		0xc0
#define	IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_3895	        0
#define	IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_7991	        1
#define	IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454	        2

#define IEEE80211_EHT_MAC_CAP1_MAX_AMPDU_LEN_MASK		0x01

/* EHT PHY capabilities as defined in P802.11be_D1.4 section 9.4.2.313.3 */
#define IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ			0x02
@@ -2949,8 +2964,13 @@ ieee80211_eht_oper_size_ok(const u8 *data, u8 len)
	if (len < needed)
		return false;

	if (elem->present_bm & IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT)
	if (elem->params & IEEE80211_EHT_OPER_INFO_PRESENT) {
		needed += 3;

		if (elem->params &
		    IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT)
			needed += 2;
	}

	return len >= needed;
}
+4 −0
Original line number Diff line number Diff line
@@ -2326,6 +2326,10 @@ bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw, u32 vht_cap_info,
				const struct ieee80211_vht_operation *oper,
				const struct ieee80211_ht_operation *htop,
				struct cfg80211_chan_def *chandef);
void ieee80211_chandef_eht_oper(struct ieee80211_sub_if_data *sdata,
				const struct ieee80211_eht_operation *eht_oper,
				bool support_160, bool support_320,
				struct cfg80211_chan_def *chandef);
bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
				    const struct ieee80211_he_operation *he_oper,
				    const struct ieee80211_eht_operation *eht_oper,
+32 −0
Original line number Diff line number Diff line
@@ -303,6 +303,38 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,

	*chandef = vht_chandef;

	/*
	 * handle the case that the EHT operation indicates that it holds EHT
	 * operation information (in case that the channel width differs from
	 * the channel width reported in HT/VHT/HE).
	 */
	if (eht_oper && (eht_oper->params & IEEE80211_EHT_OPER_INFO_PRESENT)) {
		struct cfg80211_chan_def eht_chandef = *chandef;

		ieee80211_chandef_eht_oper(sdata, eht_oper,
					   eht_chandef.width ==
					   NL80211_CHAN_WIDTH_160,
					   false, &eht_chandef);

		if (!cfg80211_chandef_valid(&eht_chandef)) {
			if (!(ifmgd->flags & IEEE80211_STA_DISABLE_EHT))
				sdata_info(sdata,
					   "AP EHT information is invalid, disabling EHT\n");
			ret = IEEE80211_STA_DISABLE_EHT;
			goto out;
		}

		if (!cfg80211_chandef_compatible(chandef, &eht_chandef)) {
			if (!(ifmgd->flags & IEEE80211_STA_DISABLE_EHT))
				sdata_info(sdata,
					   "AP EHT information is incompatible, disabling EHT\n");
			ret = IEEE80211_STA_DISABLE_EHT;
			goto out;
		}

		*chandef = eht_chandef;
	}

	ret = 0;

out:
+56 −31
Original line number Diff line number Diff line
@@ -3459,6 +3459,58 @@ bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw, u32 vht_cap_info,
	return true;
}

void ieee80211_chandef_eht_oper(struct ieee80211_sub_if_data *sdata,
				const struct ieee80211_eht_operation *eht_oper,
				bool support_160, bool support_320,
				struct cfg80211_chan_def *chandef)
{
	struct ieee80211_eht_operation_info *info = (void *)eht_oper->optional;

	chandef->center_freq1 =
		ieee80211_channel_to_frequency(info->ccfs0,
					       chandef->chan->band);

	switch (u8_get_bits(info->control,
			    IEEE80211_EHT_OPER_CHAN_WIDTH)) {
	case IEEE80211_EHT_OPER_CHAN_WIDTH_20MHZ:
		chandef->width = NL80211_CHAN_WIDTH_20;
		break;
	case IEEE80211_EHT_OPER_CHAN_WIDTH_40MHZ:
		chandef->width = NL80211_CHAN_WIDTH_40;
		break;
	case IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ:
		chandef->width = NL80211_CHAN_WIDTH_80;
		break;
	case IEEE80211_EHT_OPER_CHAN_WIDTH_160MHZ:
		if (support_160) {
			chandef->width = NL80211_CHAN_WIDTH_160;
			chandef->center_freq1 =
				ieee80211_channel_to_frequency(info->ccfs1,
							       chandef->chan->band);
		} else {
			chandef->width = NL80211_CHAN_WIDTH_80;
		}
		break;
	case IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ:
		if (support_320) {
			chandef->width = NL80211_CHAN_WIDTH_320;
			chandef->center_freq1 =
				ieee80211_channel_to_frequency(info->ccfs1,
							       chandef->chan->band);
		} else if (support_160) {
			chandef->width = NL80211_CHAN_WIDTH_160;
		} else {
			chandef->width = NL80211_CHAN_WIDTH_80;

			if (chandef->center_freq1 > chandef->chan->center_freq)
				chandef->center_freq1 -= 40;
			else
				chandef->center_freq1 += 40;
		}
		break;
	}
}

bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
				    const struct ieee80211_he_operation *he_oper,
				    const struct ieee80211_eht_operation *eht_oper,
@@ -3539,7 +3591,8 @@ bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
		break;
	}

	if (!eht_oper) {
	if (!eht_oper ||
	    !(eht_oper->params & IEEE80211_EHT_OPER_INFO_PRESENT)) {
		switch (u8_get_bits(he_6ghz_oper->control,
				    IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH)) {
		case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_20MHZ:
@@ -3583,36 +3636,8 @@ bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
		support_320 =
			eht_phy_cap & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;

		switch (u8_get_bits(eht_oper->chan_width,
				    IEEE80211_EHT_OPER_CHAN_WIDTH)) {
		case IEEE80211_EHT_OPER_CHAN_WIDTH_20MHZ:
			he_chandef.width = NL80211_CHAN_WIDTH_20;
			break;
		case IEEE80211_EHT_OPER_CHAN_WIDTH_40MHZ:
			he_chandef.width = NL80211_CHAN_WIDTH_40;
			break;
		case IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ:
			he_chandef.width = NL80211_CHAN_WIDTH_80;
			break;
		case IEEE80211_EHT_OPER_CHAN_WIDTH_160MHZ:
			if (support_160)
				he_chandef.width = NL80211_CHAN_WIDTH_160;
			else
				he_chandef.width = NL80211_CHAN_WIDTH_80;
			break;
		case IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ:
			if (support_320)
				he_chandef.width = NL80211_CHAN_WIDTH_320;
			else if (support_160)
				he_chandef.width = NL80211_CHAN_WIDTH_160;
			else
				he_chandef.width = NL80211_CHAN_WIDTH_80;
			break;
		}

		he_chandef.center_freq1 =
			ieee80211_channel_to_frequency(eht_oper->ccfs,
						       NL80211_BAND_6GHZ);
		ieee80211_chandef_eht_oper(sdata, eht_oper, support_160,
					   support_320, &he_chandef);
	}

	if (!cfg80211_chandef_valid(&he_chandef)) {