return len >= needed;
 }
 
+#define IEEE80211_BW_IND_DIS_SUBCH_PRESENT     BIT(1)
+
+struct ieee80211_bandwidth_indication {
+       u8 params;
+       struct ieee80211_eht_operation_info info;
+} __packed;
+
+static inline bool
+ieee80211_bandwidth_indication_size_ok(const u8 *data, u8 len)
+{
+       const struct ieee80211_bandwidth_indication *bwi = (const void *)data;
+
+       if (len < sizeof(*bwi))
+               return false;
+
+       if (bwi->params & IEEE80211_BW_IND_DIS_SUBCH_PRESENT &&
+           len < sizeof(*bwi) + 2)
+               return false;
+
+       return true;
+}
+
 #define LISTEN_INT_USF GENMASK(15, 14)
 #define LISTEN_INT_UI  GENMASK(13, 0)
 
        WLAN_EID_EXT_EHT_OPERATION = 106,
        WLAN_EID_EXT_EHT_MULTI_LINK = 107,
        WLAN_EID_EXT_EHT_CAPABILITY = 108,
+       WLAN_EID_EXT_BANDWIDTH_INDICATION = 135,
 };
 
 /* Action category code */
 
        const struct ieee80211_eht_operation *eht_operation;
        const struct ieee80211_multi_link_elem *ml_basic;
        const struct ieee80211_multi_link_elem *ml_reconf;
+       const struct ieee80211_bandwidth_indication *bandwidth_indication;
 
        /* length of them, respectively */
        u8 ext_capab_len;
                                const struct ieee80211_vht_operation *oper,
                                const struct ieee80211_ht_operation *htop,
                                struct cfg80211_chan_def *chandef);
-void ieee80211_chandef_eht_oper(const struct ieee80211_eht_operation *eht_oper,
+void ieee80211_chandef_eht_oper(const struct ieee80211_eht_operation_info *info,
                                bool support_160, bool support_320,
                                struct cfg80211_chan_def *chandef);
 bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
 
                return 0;
 
        /* set 160/320 supported to get the full AP definition */
-       ieee80211_chandef_eht_oper(eht_oper, true, true, &ap_chandef);
+       ieee80211_chandef_eht_oper((const void *)eht_oper->optional,
+                                  true, true, &ap_chandef);
        ap_center_freq = ap_chandef.center_freq1;
        ap_bw = 20 * BIT(u8_get_bits(info->control,
                                     IEEE80211_EHT_OPER_CHAN_WIDTH));
        if (eht_oper && (eht_oper->params & IEEE80211_EHT_OPER_INFO_PRESENT)) {
                struct cfg80211_chan_def eht_chandef = *chandef;
 
-               ieee80211_chandef_eht_oper(eht_oper,
+               ieee80211_chandef_eht_oper((const void *)eht_oper->optional,
                                           eht_chandef.width ==
                                           NL80211_CHAN_WIDTH_160,
                                           false, &eht_chandef);
 
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007-2008, Intel Corporation
  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
- * Copyright (C) 2018, 2020, 2022 Intel Corporation
+ * Copyright (C) 2018, 2020, 2022-2023 Intel Corporation
  */
 
 #include <linux/ieee80211.h>
        struct cfg80211_chan_def new_vht_chandef = {};
        const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
        const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
+       const struct ieee80211_bandwidth_indication *bwi;
        int secondary_channel_offset = -1;
 
        memset(csa_ie, 0, sizeof(*csa_ie));
 
        sec_chan_offs = elems->sec_chan_offs;
        wide_bw_chansw_ie = elems->wide_bw_chansw_ie;
+       bwi = elems->bandwidth_indication;
 
        if (conn_flags & (IEEE80211_CONN_DISABLE_HT |
                          IEEE80211_CONN_DISABLE_40MHZ)) {
                break;
        }
 
-       if (wide_bw_chansw_ie) {
+       if (bwi) {
+               /* start with the CSA one */
+               new_vht_chandef = csa_ie->chandef;
+               /* and update the width accordingly */
+               /* FIXME: support 160/320 */
+               ieee80211_chandef_eht_oper(&bwi->info, true, true,
+                                          &new_vht_chandef);
+       } else if (wide_bw_chansw_ie) {
                u8 new_seg1 = wide_bw_chansw_ie->new_center_freq_seg1;
                struct ieee80211_vht_operation vht_oper = {
                        .chan_width =
 
                        }
                }
                break;
+       case WLAN_EID_EXT_BANDWIDTH_INDICATION:
+               if (ieee80211_bandwidth_indication_size_ok(data, len))
+                       elems->bandwidth_indication = data;
+               calc_crc = true;
+               break;
        }
 
        if (crc && calc_crc)
        bool calc_crc = params->filter != 0;
        DECLARE_BITMAP(seen_elems, 256);
        u32 crc = params->crc;
-       const u8 *ie;
 
        bitmap_zero(seen_elems, 256);
 
        for_each_element(elem, params->start, params->len) {
+               const struct element *subelem;
                bool elem_parse_failed;
                u8 id = elem->id;
                u8 elen = elem->datalen;
                        }
                        /*
                         * This is a bit tricky, but as we only care about
-                        * the wide bandwidth channel switch element, so
-                        * just parse it out manually.
+                        * a few elements, parse them out manually.
                         */
-                       ie = cfg80211_find_ie(WLAN_EID_WIDE_BW_CHANNEL_SWITCH,
-                                             pos, elen);
-                       if (ie) {
-                               if (ie[1] >= sizeof(*elems->wide_bw_chansw_ie))
+                       subelem = cfg80211_find_elem(WLAN_EID_WIDE_BW_CHANNEL_SWITCH,
+                                                    pos, elen);
+                       if (subelem) {
+                               if (subelem->datalen >= sizeof(*elems->wide_bw_chansw_ie))
                                        elems->wide_bw_chansw_ie =
-                                               (void *)(ie + 2);
+                                               (void *)subelem->data;
+                               else
+                                       elem_parse_failed = true;
+                       }
+
+                       subelem = cfg80211_find_ext_elem(WLAN_EID_EXT_BANDWIDTH_INDICATION,
+                                                        pos, elen);
+                       if (subelem) {
+                               const void *edata = subelem->data + 1;
+                               u8 edatalen = subelem->datalen - 1;
+
+                               if (ieee80211_bandwidth_indication_size_ok(edata,
+                                                                          edatalen))
+                                       elems->bandwidth_indication = edata;
                                else
                                        elem_parse_failed = true;
                        }
        return true;
 }
 
-void ieee80211_chandef_eht_oper(const struct ieee80211_eht_operation *eht_oper,
+void ieee80211_chandef_eht_oper(const struct ieee80211_eht_operation_info *info,
                                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);
                support_320 =
                        eht_phy_cap & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
 
-               ieee80211_chandef_eht_oper(eht_oper, support_160,
-                                          support_320, &he_chandef);
+               ieee80211_chandef_eht_oper((const void *)eht_oper->optional,
+                                          support_160, support_320,
+                                          &he_chandef);
        }
 
        if (!cfg80211_chandef_valid(&he_chandef)) {