]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: mt76: mt7996: Add eMLSR support
authorMeiChia Chiu <MeiChia.Chiu@mediatek.com>
Tue, 3 Feb 2026 08:32:02 +0000 (09:32 +0100)
committerFelix Fietkau <nbd@nbd.name>
Tue, 24 Mar 2026 15:49:30 +0000 (15:49 +0000)
Implement set_eml_op_mode mac80211 callback in order to introduce eMLSR
support.

Tested-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260203-mt7996-emlsr-v1-1-38ffb3d5110c@kernel.org
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
drivers/net/wireless/mediatek/mt76/mt7996/main.c
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h

index 0809318c1ec2e2dafe704a22fb38a5fc4decf663..fd9cf9c0c32fee5a661bcde99111b9942be3fbcb 100644 (file)
@@ -628,6 +628,13 @@ struct sta_rec_tx_proc {
        __le32 flag;
 } __packed;
 
+struct sta_rec_eml_op {
+       __le16 tag;
+       __le16 len;
+       u8 link_bitmap;
+       u8 link_ant_num[3];
+} __packed;
+
 /* wtbl_rec */
 
 struct wtbl_req_hdr {
@@ -796,6 +803,7 @@ struct wtbl_raw {
                                         sizeof(struct sta_rec_he_6g_capa) + \
                                         sizeof(struct sta_rec_pn_info) + \
                                         sizeof(struct sta_rec_tx_proc) + \
+                                        sizeof(struct sta_rec_eml_op) + \
                                         sizeof(struct tlv) +           \
                                         MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
 
@@ -832,6 +840,7 @@ enum {
        STA_REC_PN_INFO = 0x26,
        STA_REC_KEY_V3 = 0x27,
        STA_REC_HDRT = 0x28,
+       STA_REC_EML_OP = 0x29,
        STA_REC_HDR_TRANS = 0x2B,
        STA_REC_MAX_NUM
 };
index c0fae7aec1aecadd377b53c990ef1f9ecdce70de..c6d14f09fd10dd1e69330f4c9b29e2b559c3be96 100644 (file)
@@ -2366,6 +2366,21 @@ mt7996_reconfig_complete(struct ieee80211_hw *hw,
                                             MT7996_WATCHDOG_TIME);
 }
 
+static int
+mt7996_set_eml_op_mode(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                      struct ieee80211_sta *sta,
+                      struct ieee80211_eml_params *eml_params)
+{
+       struct mt7996_dev *dev = mt7996_hw_dev(hw);
+       int ret;
+
+       mutex_lock(&dev->mt76.mutex);
+       ret = mt7996_mcu_set_emlsr_mode(dev, vif, sta, eml_params);
+       mutex_unlock(&dev->mt76.mutex);
+
+       return ret;
+}
+
 const struct ieee80211_ops mt7996_ops = {
        .add_chanctx = mt76_add_chanctx,
        .remove_chanctx = mt76_remove_chanctx,
@@ -2429,4 +2444,5 @@ const struct ieee80211_ops mt7996_ops = {
        .change_vif_links = mt7996_change_vif_links,
        .change_sta_links = mt7996_mac_sta_change_links,
        .reconfig_complete = mt7996_reconfig_complete,
+       .set_eml_op_mode = mt7996_set_eml_op_mode,
 };
index c632abe54707ff0b645d3a4a990b2abfa2b5bfe3..8e06f7fe479ca08edf08141ef9bd41239ca465dc 100644 (file)
@@ -1304,6 +1304,61 @@ int mt7996_mcu_set_protection(struct mt7996_phy *phy, struct mt7996_vif_link *li
                                     MCU_WM_UNI_CMD(BSS_INFO_UPDATE), true);
 }
 
+int mt7996_mcu_set_emlsr_mode(struct mt7996_dev *dev,
+                             struct ieee80211_vif *vif,
+                             struct ieee80211_sta *sta,
+                             struct ieee80211_eml_params *eml_params)
+{
+       struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+       struct mt7996_sta_link *msta_link;
+       struct sta_rec_eml_op *eml_op;
+       struct mt7996_vif_link *link;
+       struct sk_buff *skb;
+       struct tlv *tlv;
+
+       msta_link = mt76_dereference(msta->link[eml_params->link_id],
+                                    &dev->mt76);
+       if (!msta_link)
+               return -EINVAL;
+
+       link = mt7996_vif_link(dev, vif, eml_params->link_id);
+       if (!link)
+               return -EINVAL;
+
+       skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
+                                             &msta_link->wcid,
+                                             MT7996_STA_UPDATE_MAX_SIZE);
+       if (IS_ERR(skb))
+               return PTR_ERR(skb);
+
+       tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EML_OP, sizeof(*eml_op));
+       eml_op = (struct sta_rec_eml_op *)tlv;
+       eml_op->link_bitmap = 0;
+
+       if (eml_params->control & IEEE80211_EML_CTRL_EMLSR_MODE) {
+               unsigned long link_bitmap = eml_params->link_bitmap;
+               unsigned int link_id;
+
+               for_each_set_bit(link_id, &link_bitmap,
+                                IEEE80211_MLD_MAX_NUM_LINKS) {
+                       struct mt76_phy *mphy;
+
+                       link = mt7996_vif_link(dev, vif, link_id);
+                       if (!link)
+                               continue;
+
+                       mphy = mt76_vif_link_phy(&link->mt76);
+                       if (!mphy)
+                               continue;
+
+                       eml_op->link_bitmap |= BIT(mphy->band_idx);
+               }
+       }
+
+       return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+                                    MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
+}
+
 int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif,
                          struct ieee80211_bss_conf *link_conf)
 {
index 5f574ebe81ccb65ec45c1c8681792f699eea5a7f..ee3564c0115a36ea592741f34025a9f9f701315c 100644 (file)
@@ -901,6 +901,10 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
                                     struct mt7996_vif_link *link,
                                     struct mt7996_sta_link *msta_link);
 int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode);
+int mt7996_mcu_set_emlsr_mode(struct mt7996_dev *dev,
+                             struct ieee80211_vif *vif,
+                             struct ieee80211_sta *sta,
+                             struct ieee80211_eml_params *eml_params);
 #ifdef CONFIG_MAC80211_DEBUGFS
 void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                            struct ieee80211_sta *sta, struct dentry *dir);