]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: mac80211: clarify per-STA bandwidth handling
authorJohannes Berg <johannes.berg@intel.com>
Wed, 15 Apr 2026 12:42:17 +0000 (14:42 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 28 Apr 2026 07:29:02 +0000 (09:29 +0200)
The per-STA bandwidth handling is completely confusing, given
the function names etc.

Move everything to sta_info.c and rename the functions to
accurately reflect what they return:
 - ieee80211_sta_bw_capability()
 - ieee80211_sta_current_bw() can return the appropriate
   bandwidth in the desired direction (a new enum)

At any given time, the bandwidth with which we expect to receive
frames from a station may differ from the bandwidth with which
we may transmit frames to the station; this will happen either
during RX OMI negotiation, or for a long time if the station
used an HT Notify Channel Width frame. We also implement the
(VHT) Operating Mode Notification as an asymmetric setting, even
if the spec would seem to imply it could be symmetric.

Also rename the 'cur_max_bandwidth' value to 'op_mode_bw' which
matches the 'op_mode_nss', indicating more clearly what it _is_
rather than how it's _used_. It's not quite precise (NSS is)
since it's also HT chanwidth notification, but that seems OK.

Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260415144514.09ae71b74d5c.Ib59c2ac82e030559d1f7d462f06ba3488a090946@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/chan.c
net/mac80211/he.c
net/mac80211/ht.c
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/tdls.c
net/mac80211/vht.c

index 13c0d080ef2ae53c738bb6d302affa6cdb514e9c..ecc0123ed44828c8a93273492ce7fdc856a57ee4 100644 (file)
@@ -455,10 +455,10 @@ ieee80211_get_sta_bw(struct sta_info *sta, struct ieee80211_link_data *link)
         * We assume that TX/RX might be asymmetric (so e.g. VHT operating
         * mode notification changes what a STA wants to receive, but not
         * necessarily what it will transmit to us), and therefore use the
-        * capabilities here. Calling it RX bandwidth capability is a bit
-        * wrong though, since capabilities are in fact symmetric.
+        * "from station" bandwidth here.
         */
-       width = ieee80211_sta_cap_rx_bw(link_sta, &link->conf->chanreq.oper);
+       width = ieee80211_sta_current_bw(link_sta, &link->conf->chanreq.oper,
+                                        IEEE80211_STA_BW_RX_FROM_STA);
 
        if (width == IEEE80211_STA_RX_BW_20 &&
            !link_sta->pub->ht_cap.ht_supported &&
@@ -693,8 +693,9 @@ static void ieee80211_chan_bw_change(struct ieee80211_local *local,
                        else
                                new_chandef = &link_conf->chanreq.oper;
 
-                       new_sta_bw = ieee80211_sta_cur_vht_bw(link_sta,
-                                                             new_chandef);
+                       new_sta_bw = ieee80211_sta_current_bw(link_sta,
+                                                             new_chandef,
+                                                             IEEE80211_STA_BW_TX_TO_STA);
 
                        /* nothing change */
                        if (new_sta_bw == link_sta->pub->bandwidth)
index 1e8ce33bfe2e6be8aee40b6e3ebb6a359f910b4c..b7d9e4cb6ba6eeafee51b198e140e67985042d12 100644 (file)
@@ -273,7 +273,8 @@ static void ieee80211_link_sta_rc_update_omi(struct ieee80211_link_data *link,
        band = link->conf->chanreq.oper.chan->band;
        sband = sdata->local->hw.wiphy->bands[band];
 
-       new_bw = ieee80211_sta_cur_vht_bw(link_sta, &link->conf->chanreq.oper);
+       new_bw = ieee80211_sta_current_bw(link_sta, &link->conf->chanreq.oper,
+                                         IEEE80211_STA_BW_TX_TO_STA);
        if (link_sta->pub->bandwidth == new_bw)
                return;
 
index 02ca6e1edc495987d311fdf91bb4c342bfdc39c7..6285ac15c16c4ca75cc05ed8d44ca8df84357e12 100644 (file)
@@ -600,9 +600,10 @@ void ieee80211_ht_handle_chanwidth_notif(struct ieee80211_local *local,
        else
                max_bw = IEEE80211_STA_RX_BW_MAX;
 
-       /* set cur_max_bandwidth and recalc sta bw */
-       link_sta->cur_max_bandwidth = max_bw;
-       new_bw = ieee80211_sta_cur_vht_bw(link_sta, &link->conf->chanreq.oper);
+       /* set op_mode_bw and recalc sta bw */
+       link_sta->op_mode_bw = max_bw;
+       new_bw = ieee80211_sta_current_bw(link_sta, &link->conf->chanreq.oper,
+                                         IEEE80211_STA_BW_TX_TO_STA);
 
        if (link_sta->pub->bandwidth == new_bw)
                return;
index 6b72be762dbe687d40b70778687d8aa24bb2b9e4..f1bab633697eb1bb5aead44e6389616b382a27d8 100644 (file)
@@ -2299,13 +2299,6 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
                                    const struct ieee80211_vht_cap *vht_cap_ie,
                                    const struct ieee80211_vht_cap *vht_cap_ie2,
                                    struct link_sta_info *link_sta);
-enum ieee80211_sta_rx_bandwidth
-ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta,
-                       struct cfg80211_chan_def *chandef);
-enum ieee80211_sta_rx_bandwidth
-ieee80211_sta_cur_vht_bw(struct link_sta_info *link_sta,
-                        struct cfg80211_chan_def *chandef);
-
 void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata,
                                 struct ieee80211_link_data *link,
                                 struct ieee80211_mgmt *mgmt);
index 6e0e5d3f5015d3a6309566e7b209701d500663a6..00b4beff0e436637f9b8eaabd887020e8ddd57bf 100644 (file)
@@ -2571,8 +2571,9 @@ static void ieee80211_csa_switch_work(struct wiphy *wiphy,
                        return;
 
                link_sta->pub->bandwidth =
-                       ieee80211_sta_cur_vht_bw(link_sta,
-                                                &link->csa.chanreq.oper);
+                       ieee80211_sta_current_bw(link_sta,
+                                                &link->csa.chanreq.oper,
+                                                IEEE80211_STA_BW_TX_TO_STA);
                return;
        }
 
index 508aad14bdf631b2e8fdaa53fbda9acb5f359021..ec043d88a6a91af13844d90f121da6c0d8049f85 100644 (file)
@@ -572,13 +572,13 @@ static int sta_info_alloc_link(struct ieee80211_local *local,
        link_info->rx_omi_bw_tx = IEEE80211_STA_RX_BW_MAX;
        link_info->rx_omi_bw_staging = IEEE80211_STA_RX_BW_MAX;
 
-       link_info->cur_max_bandwidth = IEEE80211_STA_RX_BW_MAX;
+       link_info->op_mode_bw = IEEE80211_STA_RX_BW_MAX;
 
        /*
         * Cause (a) warning(s) if IEEE80211_STA_RX_BW_MAX != 320
         * or if new values are added to the enum.
         */
-       switch (link_info->cur_max_bandwidth) {
+       switch (link_info->op_mode_bw) {
        case IEEE80211_STA_RX_BW_20:
        case IEEE80211_STA_RX_BW_40:
        case IEEE80211_STA_RX_BW_80:
@@ -3519,7 +3519,9 @@ void ieee80211_sta_init_nss_bw_capa(struct link_sta_info *link_sta,
        link_sta->capa_nss = ieee80211_sta_nss_capability(link_sta);
        link_sta->pub->rx_nss = link_sta->capa_nss;
 
-       link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta, chandef);
+       link_sta->pub->bandwidth =
+               ieee80211_sta_current_bw(link_sta, chandef,
+                                        IEEE80211_STA_BW_TX_TO_STA);
 }
 
 void ieee80211_sta_set_max_amsdu_subframes(struct sta_info *sta,
@@ -3554,3 +3556,152 @@ bool lockdep_sta_mutex_held(struct ieee80211_sta *pubsta)
 }
 EXPORT_SYMBOL(lockdep_sta_mutex_held);
 #endif
+
+/**
+ * ieee80211_sta_bw_capability - get STA's bandwidth capability
+ * @link_sta: the (link) STA to get the capability for
+ * @band: the band to get the capability on
+ *
+ * Return: the maximum bandwidth supported by the STA
+ */
+static enum ieee80211_sta_rx_bandwidth
+ieee80211_sta_bw_capability(struct link_sta_info *link_sta,
+                           enum nl80211_band band)
+{
+       struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap;
+       struct ieee80211_sta_he_cap *he_cap = &link_sta->pub->he_cap;
+       struct ieee80211_sta_eht_cap *eht_cap = &link_sta->pub->eht_cap;
+       u32 cap_width;
+
+       if (he_cap->has_he) {
+               u8 info;
+
+               if (eht_cap->has_eht && band == NL80211_BAND_6GHZ) {
+                       info = eht_cap->eht_cap_elem.phy_cap_info[0];
+
+                       if (info & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
+                               return IEEE80211_STA_RX_BW_320;
+               }
+
+               info = he_cap->he_cap_elem.phy_cap_info[0];
+
+               if (band == NL80211_BAND_2GHZ) {
+                       if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G)
+                               return IEEE80211_STA_RX_BW_40;
+                       return IEEE80211_STA_RX_BW_20;
+               }
+
+               if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G ||
+                   info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
+                       return IEEE80211_STA_RX_BW_160;
+
+               if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)
+                       return IEEE80211_STA_RX_BW_80;
+
+               return IEEE80211_STA_RX_BW_20;
+       }
+
+       if (!vht_cap->vht_supported)
+               return link_sta->pub->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
+                               IEEE80211_STA_RX_BW_40 :
+                               IEEE80211_STA_RX_BW_20;
+
+       cap_width = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
+
+       if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ||
+           cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
+               return IEEE80211_STA_RX_BW_160;
+
+       /*
+        * If this is non-zero, then it does support 160 MHz after all,
+        * in one form or the other. We don't distinguish here (or even
+        * above) between 160 and 80+80 yet.
+        */
+       if (vht_cap->cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK)
+               return IEEE80211_STA_RX_BW_160;
+
+       return IEEE80211_STA_RX_BW_80;
+}
+
+static enum ieee80211_sta_rx_bandwidth
+ieee80211_sta_current_bw_rx_from_sta(struct link_sta_info *link_sta,
+                                    struct cfg80211_chan_def *chandef)
+{
+       /*
+        * Take RX OMI into account. The value "rx_omi_bw_rx" is what
+        * we've indicated to the STA we can currently receive.
+        *
+        * This is needed since the RX OMI is done by us to save power,
+        * requiring changing both our TX (rate control) and RX (chanctx),
+        * which in turn needs to be done in the right order (stop TX
+        * at a higher bandwidth first while reducing bandwidth, and
+        * change the chanctx only after the peer accepts, etc.)
+        */
+       return min(ieee80211_sta_bw_capability(link_sta, chandef->chan->band),
+                  link_sta->rx_omi_bw_rx);
+}
+
+static enum ieee80211_sta_rx_bandwidth
+ieee80211_sta_current_bw_tx_to_sta(struct link_sta_info *link_sta,
+                                  struct cfg80211_chan_def *chandef)
+{
+       struct sta_info *sta = link_sta->sta;
+       enum nl80211_chan_width bss_width;
+       enum ieee80211_sta_rx_bandwidth bw;
+       enum nl80211_band band;
+
+       bss_width = chandef->width;
+       band = chandef->chan->band;
+
+       bw = ieee80211_sta_bw_capability(link_sta, band);
+       bw = min(bw, link_sta->op_mode_bw);
+       /* also limit to RX OMI bandwidth we TX to the STA */
+       bw = min(bw, link_sta->rx_omi_bw_tx);
+
+       /* Don't consider AP's bandwidth for TDLS peers, section 11.23.1 of
+        * IEEE80211-2016 specification makes higher bandwidth operation
+        * possible on the TDLS link if the peers have wider bandwidth
+        * capability.
+        *
+        * However, in this case, and only if the TDLS peer is authorized,
+        * limit to the tdls_chandef so that the configuration here isn't
+        * wider than what's actually requested on the channel context.
+        */
+       if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
+           test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW) &&
+           test_sta_flag(sta, WLAN_STA_AUTHORIZED) &&
+           sta->tdls_chandef.chan)
+               bw = min(bw, ieee80211_chan_width_to_rx_bw(sta->tdls_chandef.width));
+       else
+               bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width));
+
+       return bw;
+}
+
+/**
+ * ieee80211_sta_current_bw - get STA's current usable bandwidth
+ * @link_sta: the (link) STA to get the bandwidth for
+ * @chandef: the chandef for the channel the STA is on
+ * @direction: the direction (to or from STA)
+ *
+ * Return: the maximum bandwidth that the station can/may
+ *     (currently) use in the given direction
+ */
+enum ieee80211_sta_rx_bandwidth
+ieee80211_sta_current_bw(struct link_sta_info *link_sta,
+                        struct cfg80211_chan_def *chandef,
+                        enum ieee80211_sta_bw_direction direction)
+{
+       if (WARN_ON(!chandef))
+               return IEEE80211_STA_RX_BW_20;
+
+       switch (direction) {
+       case IEEE80211_STA_BW_RX_FROM_STA:
+               return ieee80211_sta_current_bw_rx_from_sta(link_sta, chandef);
+       case IEEE80211_STA_BW_TX_TO_STA:
+               return ieee80211_sta_current_bw_tx_to_sta(link_sta, chandef);
+       }
+
+       /* unreachable */
+       return IEEE80211_STA_RX_BW_20;
+}
index f0497d7d488a97110c388e09cb81b5200a2b3f3a..39608a0abbb5932178b4d6dd99bfc284c646944c 100644 (file)
@@ -504,7 +504,7 @@ struct ieee80211_fragment_cache {
  * @status_stats.last_ack_signal: last ACK signal
  * @status_stats.ack_signal_filled: last ACK signal validity
  * @status_stats.avg_ack_signal: average ACK signal
- * @cur_max_bandwidth: dynamic bandwidth limit for the station,
+ * @op_mode_bw: dynamic bandwidth limit to transmit to the STA,
  *     taken from HT/VHT capabilities or VHT operating mode notification.
  *     Invalid for NAN since that is operating on multiple bands.
  * @rx_omi_bw_rx: RX OMI bandwidth restriction to apply for RX
@@ -558,7 +558,7 @@ struct link_sta_info {
                u64 msdu[IEEE80211_NUM_TIDS + 1];
        } tx_stats;
 
-       enum ieee80211_sta_rx_bandwidth cur_max_bandwidth;
+       enum ieee80211_sta_rx_bandwidth op_mode_bw;
        enum ieee80211_sta_rx_bandwidth rx_omi_bw_rx,
                                        rx_omi_bw_tx,
                                        rx_omi_bw_staging;
@@ -1005,6 +1005,16 @@ void ieee80211_sta_set_max_amsdu_subframes(struct sta_info *sta,
 
 void __ieee80211_sta_recalc_aggregates(struct sta_info *sta, u16 active_links);
 
+enum ieee80211_sta_bw_direction {
+       IEEE80211_STA_BW_RX_FROM_STA,
+       IEEE80211_STA_BW_TX_TO_STA,
+};
+
+enum ieee80211_sta_rx_bandwidth
+ieee80211_sta_current_bw(struct link_sta_info *link_sta,
+                        struct cfg80211_chan_def *chandef,
+                        enum ieee80211_sta_bw_direction direction);
+
 enum sta_stats_type {
        STA_STATS_RATE_TYPE_INVALID = 0,
        STA_STATS_RATE_TYPE_LEGACY,
index dcb5fe98ec55b5fd67e5cf4f9928f468bd02814f..ffd575a8d188faab6850581dd85a1be54290e3d0 100644 (file)
@@ -314,7 +314,8 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata,
        enum nl80211_chan_width max_width;
        int i;
 
-       switch (ieee80211_sta_cap_rx_bw(&sta->deflink, &uc)) {
+       switch (ieee80211_sta_current_bw(&sta->deflink, &uc,
+                                        IEEE80211_STA_BW_RX_FROM_STA)) {
        case IEEE80211_STA_RX_BW_20:
                max_width = NL80211_CHAN_WIDTH_20;
                break;
@@ -1337,8 +1338,9 @@ static void iee80211_tdls_recalc_chanctx(struct ieee80211_sub_if_data *sdata,
                        enum ieee80211_sta_rx_bandwidth bw;
 
                        bw = ieee80211_chan_width_to_rx_bw(conf->def.width);
-                       bw = min(bw, ieee80211_sta_cap_rx_bw(&sta->deflink,
-                                                            &conf->def));
+                       bw = min(bw, ieee80211_sta_current_bw(&sta->deflink,
+                                                             &conf->def,
+                                                             IEEE80211_STA_BW_RX_FROM_STA));
                        if (bw != sta->sta.deflink.bandwidth) {
                                sta->sta.deflink.bandwidth = bw;
                                rate_control_rate_update(local, sband,
index 3df5f6c3f777e25ee8b4b391c1df014e17a2a903..92a4e04505936b7d79c3e9fcb5818066e42b44f3 100644 (file)
@@ -331,129 +331,6 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
        ieee80211_sta_recalc_aggregates(&link_sta->sta->sta);
 }
 
-/* FIXME: move this to some better location - parses HE/EHT now */
-static enum ieee80211_sta_rx_bandwidth
-_ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta, enum nl80211_band band)
-{
-       struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap;
-       struct ieee80211_sta_he_cap *he_cap = &link_sta->pub->he_cap;
-       struct ieee80211_sta_eht_cap *eht_cap = &link_sta->pub->eht_cap;
-       u32 cap_width;
-
-       if (he_cap->has_he) {
-               u8 info;
-
-               if (eht_cap->has_eht && band == NL80211_BAND_6GHZ) {
-                       info = eht_cap->eht_cap_elem.phy_cap_info[0];
-
-                       if (info & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
-                               return IEEE80211_STA_RX_BW_320;
-               }
-
-               info = he_cap->he_cap_elem.phy_cap_info[0];
-
-               if (band == NL80211_BAND_2GHZ) {
-                       if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G)
-                               return IEEE80211_STA_RX_BW_40;
-                       return IEEE80211_STA_RX_BW_20;
-               }
-
-               if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G ||
-                   info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
-                       return IEEE80211_STA_RX_BW_160;
-
-               if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)
-                       return IEEE80211_STA_RX_BW_80;
-
-               return IEEE80211_STA_RX_BW_20;
-       }
-
-       if (!vht_cap->vht_supported)
-               return link_sta->pub->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
-                               IEEE80211_STA_RX_BW_40 :
-                               IEEE80211_STA_RX_BW_20;
-
-       cap_width = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
-
-       if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ||
-           cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
-               return IEEE80211_STA_RX_BW_160;
-
-       /*
-        * If this is non-zero, then it does support 160 MHz after all,
-        * in one form or the other. We don't distinguish here (or even
-        * above) between 160 and 80+80 yet.
-        */
-       if (vht_cap->cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK)
-               return IEEE80211_STA_RX_BW_160;
-
-       return IEEE80211_STA_RX_BW_80;
-}
-
-enum ieee80211_sta_rx_bandwidth
-ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta,
-                       struct cfg80211_chan_def *chandef)
-{
-       /*
-        * With RX OMI, also pretend that the STA's capability changed.
-        * Of course this isn't really true, it didn't change, only our
-        * RX capability was changed by notifying RX OMI to the STA.
-        * The purpose, however, is to save power, and that requires
-        * changing also transmissions to the AP and the chanctx. The
-        * transmissions depend on link_sta->bandwidth which is set in
-        * ieee80211_sta_cur_vht_bw() below, but the chanctx depends
-        * on the result of this function which is also called by
-        * ieee80211_sta_cur_vht_bw(), so we need to do that here as
-        * well. This is sufficient for the steady state, but during
-        * the transition we already need to change TX/RX separately,
-        * so ieee80211_sta_cur_vht_bw() below applies the _tx one.
-        */
-       return min(_ieee80211_sta_cap_rx_bw(link_sta, chandef->chan->band),
-                  link_sta->rx_omi_bw_rx);
-}
-
-/* FIXME: rename/move - this deals with everything not just VHT */
-enum ieee80211_sta_rx_bandwidth
-ieee80211_sta_cur_vht_bw(struct link_sta_info *link_sta,
-                        struct cfg80211_chan_def *chandef)
-{
-       struct sta_info *sta = link_sta->sta;
-       enum nl80211_chan_width bss_width;
-       enum ieee80211_sta_rx_bandwidth bw;
-       enum nl80211_band band;
-
-       if (WARN_ON(!chandef))
-               return IEEE80211_STA_RX_BW_20;
-
-       bss_width = chandef->width;
-       band = chandef->chan->band;
-
-       /* intentionally do not take rx_bw_omi_rx into account */
-       bw = _ieee80211_sta_cap_rx_bw(link_sta, band);
-       bw = min(bw, link_sta->cur_max_bandwidth);
-       /* but do apply rx_omi_bw_tx */
-       bw = min(bw, link_sta->rx_omi_bw_tx);
-
-       /* Don't consider AP's bandwidth for TDLS peers, section 11.23.1 of
-        * IEEE80211-2016 specification makes higher bandwidth operation
-        * possible on the TDLS link if the peers have wider bandwidth
-        * capability.
-        *
-        * However, in this case, and only if the TDLS peer is authorized,
-        * limit to the tdls_chandef so that the configuration here isn't
-        * wider than what's actually requested on the channel context.
-        */
-       if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
-           test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW) &&
-           test_sta_flag(sta, WLAN_STA_AUTHORIZED) &&
-           sta->tdls_chandef.chan)
-               bw = min(bw, ieee80211_chan_width_to_rx_bw(sta->tdls_chandef.width));
-       else
-               bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width));
-
-       return bw;
-}
-
 u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
                                  struct link_sta_info *link_sta,
                                  u8 opmode, enum nl80211_band band)
@@ -496,25 +373,26 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
        switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) {
        case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ:
                /* ignore IEEE80211_OPMODE_NOTIF_BW_160_80P80 must not be set */
-               link_sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_20;
+               link_sta->op_mode_bw = IEEE80211_STA_RX_BW_20;
                break;
        case IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ:
                /* ignore IEEE80211_OPMODE_NOTIF_BW_160_80P80 must not be set */
-               link_sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_40;
+               link_sta->op_mode_bw = IEEE80211_STA_RX_BW_40;
                break;
        case IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ:
                if (opmode & IEEE80211_OPMODE_NOTIF_BW_160_80P80)
-                       link_sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
+                       link_sta->op_mode_bw = IEEE80211_STA_RX_BW_160;
                else
-                       link_sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_80;
+                       link_sta->op_mode_bw = IEEE80211_STA_RX_BW_80;
                break;
        case IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ:
                /* legacy only, no longer used by newer spec */
-               link_sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
+               link_sta->op_mode_bw = IEEE80211_STA_RX_BW_160;
                break;
        }
 
-       new_bw = ieee80211_sta_cur_vht_bw(link_sta, &link->conf->chanreq.oper);
+       new_bw = ieee80211_sta_current_bw(link_sta, &link->conf->chanreq.oper,
+                                         IEEE80211_STA_BW_TX_TO_STA);
        if (new_bw != link_sta->pub->bandwidth) {
                link_sta->pub->bandwidth = new_bw;
                sta_opmode.bw = ieee80211_sta_rx_bw_to_chan_width(new_bw);