]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: iwlwifi: mld: enable UHR in TLC
authorJohannes Berg <johannes.berg@intel.com>
Fri, 20 Mar 2026 08:09:04 +0000 (10:09 +0200)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Wed, 25 Mar 2026 09:31:57 +0000 (11:31 +0200)
Tell the firmware if UHR is supported, including ELR (enhanced
long range) MCS support.

Note that the spec currently doesn't differentiate between 1.5
and 3 Mbps ELR MCSes, unlike the firmware.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260320100746.7117009d7c39.If4e8cdc63fdf4c5f14d923a5c59fb7b43df72a67@changeid
drivers/net/wireless/intel/iwlwifi/mld/tlc.c

index 62a54c37a98c53c19e801746bcd18e51d68abda3..ede385909e38f20eb480712e2ac727233e2dc2da 100644 (file)
@@ -36,7 +36,8 @@ iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld,
                          struct ieee80211_vif *vif,
                          struct ieee80211_link_sta *link_sta,
                          const struct ieee80211_sta_he_cap *own_he_cap,
-                         const struct ieee80211_sta_eht_cap *own_eht_cap)
+                         const struct ieee80211_sta_eht_cap *own_eht_cap,
+                         const struct ieee80211_sta_uhr_cap *own_uhr_cap)
 {
        struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
        struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
@@ -90,6 +91,12 @@ iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld,
                flags |= IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK;
        }
 
+       if (link_sta->uhr_cap.has_uhr && own_uhr_cap &&
+           link_sta->uhr_cap.phy.cap & IEEE80211_UHR_PHY_CAP_ELR_RX &&
+           own_uhr_cap->phy.cap & IEEE80211_UHR_PHY_CAP_ELR_TX)
+               flags |= IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_1_5_MBPS_MSK |
+                        IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_3_MBPS_MSK;
+
        return cpu_to_le16(flags);
 }
 
@@ -406,6 +413,7 @@ iwl_mld_fill_supp_rates(struct iwl_mld *mld, struct ieee80211_vif *vif,
                        struct ieee80211_supported_band *sband,
                        const struct ieee80211_sta_he_cap *own_he_cap,
                        const struct ieee80211_sta_eht_cap *own_eht_cap,
+                       const struct ieee80211_sta_uhr_cap *own_uhr_cap,
                        struct iwl_tlc_config_cmd *cmd)
 {
        int i;
@@ -423,7 +431,16 @@ iwl_mld_fill_supp_rates(struct iwl_mld *mld, struct ieee80211_vif *vif,
        cmd->non_ht_rates = cpu_to_le16(non_ht_rates);
        cmd->mode = IWL_TLC_MNG_MODE_NON_HT;
 
-       if (link_sta->eht_cap.has_eht && own_he_cap && own_eht_cap) {
+       if (link_sta->uhr_cap.has_uhr && own_uhr_cap) {
+               cmd->mode = IWL_TLC_MNG_MODE_UHR;
+               /*
+                * FIXME: spec currently inherits from EHT but has no
+                * finer MCS bits. Once that's there, need to add them
+                * to the bitmaps (and maybe copy this to UHR, or so.)
+                */
+               iwl_mld_fill_eht_rates(vif, link_sta, own_he_cap,
+                                      own_eht_cap, cmd);
+       } else if (link_sta->eht_cap.has_eht && own_he_cap && own_eht_cap) {
                cmd->mode = IWL_TLC_MNG_MODE_EHT;
                iwl_mld_fill_eht_rates(vif, link_sta, own_he_cap,
                                       own_eht_cap, cmd);
@@ -519,13 +536,16 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
                ieee80211_get_he_iftype_cap_vif(sband, vif);
        const struct ieee80211_sta_eht_cap *own_eht_cap =
                ieee80211_get_eht_iftype_cap_vif(sband, vif);
+       const struct ieee80211_sta_uhr_cap *own_uhr_cap =
+               ieee80211_get_uhr_iftype_cap_vif(sband, vif);
        struct iwl_tlc_config_cmd cmd = {
                /* For AP mode, use 20 MHz until the STA is authorized */
                .max_ch_width = mld_sta->sta_state > IEEE80211_STA_ASSOC ?
                        iwl_mld_fw_bw_from_sta_bw(link_sta) :
                        IWL_TLC_MNG_CH_WIDTH_20MHZ,
                .flags = iwl_mld_get_tlc_cmd_flags(mld, vif, link_sta,
-                                                  own_he_cap, own_eht_cap),
+                                                  own_he_cap, own_eht_cap,
+                                                  own_uhr_cap),
                .chains = iwl_mld_get_fw_chains(mld),
                .sgi_ch_width_supp = iwl_mld_get_fw_sgi(link_sta),
                .max_mpdu_len = cpu_to_le16(link_sta->agg.max_amsdu_len),
@@ -555,7 +575,7 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
 
        iwl_mld_fill_supp_rates(mld, vif, link_sta, sband,
                                own_he_cap, own_eht_cap,
-                               &cmd);
+                               own_uhr_cap, &cmd);
 
        if (cmd_ver == 6) {
                cmd_ptr = &cmd;