Loading include/linux/ieee80211.h +36 −16 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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; } Loading net/mac80211/ieee80211_i.h +4 −0 Original line number Diff line number Diff line Loading @@ -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, Loading net/mac80211/mlme.c +32 −0 Original line number Diff line number Diff line Loading @@ -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: Loading net/mac80211/util.c +56 −31 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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: Loading Loading @@ -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)) { Loading Loading
include/linux/ieee80211.h +36 −16 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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; } Loading
net/mac80211/ieee80211_i.h +4 −0 Original line number Diff line number Diff line Loading @@ -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, Loading
net/mac80211/mlme.c +32 −0 Original line number Diff line number Diff line Loading @@ -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: Loading
net/mac80211/util.c +56 −31 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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: Loading Loading @@ -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)) { Loading