wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR);
        wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
+       wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
+       wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
+       wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
+       wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
 
        ieee80211_hw_set(hw, HAS_RATE_CONTROL);
        ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
 
        txwi[7] |= cpu_to_le32(val);
 }
 
+static u16
+mt7915_mac_tx_rate_val(struct mt76_phy *mphy, struct ieee80211_vif *vif,
+                      bool beacon, bool mcast)
+{
+       u8 mode = 0, band = mphy->chandef.chan->band;
+       int rateidx = 0, mcast_rate;
+
+       if (beacon) {
+               struct cfg80211_bitrate_mask *mask;
+
+               mask = &vif->bss_conf.beacon_tx_rate;
+               if (hweight16(mask->control[band].he_mcs[0]) == 1) {
+                       rateidx = ffs(mask->control[band].he_mcs[0]) - 1;
+                       mode = MT_PHY_TYPE_HE_SU;
+                       goto out;
+               } else if (hweight16(mask->control[band].vht_mcs[0]) == 1) {
+                       rateidx = ffs(mask->control[band].vht_mcs[0]) - 1;
+                       mode = MT_PHY_TYPE_VHT;
+                       goto out;
+               } else if (hweight8(mask->control[band].ht_mcs[0]) == 1) {
+                       rateidx = ffs(mask->control[band].ht_mcs[0]) - 1;
+                       mode = MT_PHY_TYPE_HT;
+                       goto out;
+               } else if (hweight32(mask->control[band].legacy) == 1) {
+                       rateidx = ffs(mask->control[band].legacy) - 1;
+                       goto legacy;
+               }
+       }
+
+       mcast_rate = vif->bss_conf.mcast_rate[band];
+       if (mcast && mcast_rate > 0)
+               rateidx = mcast_rate - 1;
+       else
+               rateidx = ffs(vif->bss_conf.basic_rates) - 1;
+
+legacy:
+       rateidx = mt76_calculate_default_rate(mphy, rateidx);
+       mode = rateidx >> 8;
+       rateidx &= GENMASK(7, 0);
+
+out:
+       return FIELD_PREP(MT_TX_RATE_IDX, rateidx) |
+              FIELD_PREP(MT_TX_RATE_MODE, mode);
+}
+
 void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
                           struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
                           struct ieee80211_key_conf *key, bool beacon)
                mt7915_mac_write_txwi_80211(dev, txwi, skb, key, &mcast);
 
        if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) {
-               u8 band = mphy->chandef.chan->band;
-               int rateidx, mcast_rate = vif->bss_conf.mcast_rate[band];
-               u16 rate, mode;
+               u16 rate = mt7915_mac_tx_rate_val(mphy, vif, beacon, mcast);
 
                /* hardware won't add HTC for mgmt/ctrl frame */
                txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD);
 
-               if (mcast && mcast_rate > 0)
-                       rateidx = mcast_rate - 1;
-               else
-                       rateidx = ffs(vif->bss_conf.basic_rates) - 1;
-
-               rate = mt76_calculate_default_rate(mphy, rateidx);
-               mode = rate >> 8;
-               rate &= GENMASK(7, 0);
-               rate |= FIELD_PREP(MT_TX_RATE_MODE, mode);
-
                val = MT_TXD6_FIXED_BW |
                      FIELD_PREP(MT_TXD6_TX_RATE, rate);
                txwi[6] |= cpu_to_le32(val);