]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: mt76: Move RCU section in mt7996_mcu_add_rate_ctrl()
authorLorenzo Bianconi <lorenzo@kernel.org>
Thu, 5 Jun 2025 11:14:19 +0000 (13:14 +0200)
committerFelix Fietkau <nbd@nbd.name>
Mon, 7 Jul 2025 15:42:20 +0000 (17:42 +0200)
Since mt76_mcu_skb_send_msg() routine can't be executed in atomic context,
move RCU section in mt7996_mcu_add_rate_ctrl() and execute
mt76_mcu_skb_send_msg() in non-atomic context. This is a preliminary
patch to fix a 'sleep while atomic' issue in mt7996_mac_sta_rc_work().

Fixes: 0762bdd30279 ("wifi: mt76: mt7996: rework mt7996_mac_sta_rc_work to support MLO")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20250605-mt7996-sleep-while-atomic-v1-4-d46d15f9203c@kernel.org
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7996/mac.c
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 7444bd374b50bdfdcf7e1973993f496b740a1c51..329dc9edc80d73e0874e25d08aac3752be0a5fd5 100644 (file)
@@ -2356,7 +2356,6 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
        struct ieee80211_bss_conf *link_conf;
        struct ieee80211_link_sta *link_sta;
        struct mt7996_sta_link *msta_link;
-       struct mt7996_vif_link *link;
        struct mt76_vif_link *mlink;
        struct ieee80211_sta *sta;
        struct ieee80211_vif *vif;
@@ -2398,13 +2397,10 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
 
                spin_unlock_bh(&dev->mt76.sta_poll_lock);
 
-               link = (struct mt7996_vif_link *)mlink;
-
                if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED |
                               IEEE80211_RC_NSS_CHANGED |
                               IEEE80211_RC_BW_CHANGED))
-                       mt7996_mcu_add_rate_ctrl(dev, vif, link_conf,
-                                                link_sta, link, msta_link,
+                       mt7996_mcu_add_rate_ctrl(dev, msta_link->sta, vif,
                                                 link_id, true);
 
                if (changed & IEEE80211_RC_SMPS_CHANGED)
index a096b5bab001de8d4fe3270ab37b1a6dab702ab1..07dd75ce94a5f204dcd4d659a777151bb9fcf8d2 100644 (file)
@@ -1112,10 +1112,8 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
                        if (err)
                                return err;
 
-                       err = mt7996_mcu_add_rate_ctrl(dev, vif, link_conf,
-                                                      link_sta, link,
-                                                      msta_link, link_id,
-                                                      false);
+                       err = mt7996_mcu_add_rate_ctrl(dev, msta_link->sta, vif,
+                                                      link_id, false);
                        if (err)
                                return err;
 
index 742497ba2a6bcd73e3660e626e4a756d79a467bf..77ab1f4854a43643c296f6ed28c08da99bfdcb04 100644 (file)
@@ -2201,23 +2201,44 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
        memset(ra->rx_rcpi, INIT_RCPI, sizeof(ra->rx_rcpi));
 }
 
-int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
-                            struct ieee80211_vif *vif,
-                            struct ieee80211_bss_conf *link_conf,
-                            struct ieee80211_link_sta *link_sta,
-                            struct mt7996_vif_link *link,
-                            struct mt7996_sta_link *msta_link,
-                            u8 link_id, bool changed)
+int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct mt7996_sta *msta,
+                            struct ieee80211_vif *vif, u8 link_id,
+                            bool changed)
 {
-       struct mt7996_sta *msta = msta_link->sta;
+       struct ieee80211_bss_conf *link_conf;
+       struct ieee80211_link_sta *link_sta;
+       struct mt7996_sta_link *msta_link;
+       struct mt7996_vif_link *link;
+       struct ieee80211_sta *sta;
        struct sk_buff *skb;
-       int ret;
+       int ret = -ENODEV;
+
+       rcu_read_lock();
+
+       link = mt7996_vif_link(dev, vif, link_id);
+       if (!link)
+               goto error_unlock;
+
+       msta_link = rcu_dereference(msta->link[link_id]);
+       if (!msta_link)
+               goto error_unlock;
+
+       sta = wcid_to_sta(&msta_link->wcid);
+       link_sta = rcu_dereference(sta->link[link_id]);
+       if (!link_sta)
+               goto error_unlock;
+
+       link_conf = rcu_dereference(vif->link_conf[link_id]);
+       if (!link_conf)
+               goto error_unlock;
 
        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);
+       if (IS_ERR(skb)) {
+               ret = PTR_ERR(skb);
+               goto error_unlock;
+       }
 
        /* firmware rc algorithm refers to sta_rec_he for HE control.
         * once dev->rc_work changes the settings driver should also
@@ -2231,12 +2252,19 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
         */
        mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, link_conf, link_sta, link);
 
+       rcu_read_unlock();
+
        ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
                                    MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
        if (ret)
                return ret;
 
        return mt7996_mcu_add_rate_ctrl_fixed(dev, msta, vif, link_id);
+
+error_unlock:
+       rcu_read_unlock();
+
+       return ret;
 }
 
 static int
index a529c2bae7cbf83589650c593f033e6ec5e714a8..33ac16b64ef113eff3f7749963e34a49b3c67ac3 100644 (file)
@@ -620,13 +620,9 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
 int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy,
                            struct mt7996_vif_link *link,
                            struct ieee80211_he_obss_pd *he_obss_pd);
-int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
-                            struct ieee80211_vif *vif,
-                            struct ieee80211_bss_conf *link_conf,
-                            struct ieee80211_link_sta *link_sta,
-                            struct mt7996_vif_link *link,
-                            struct mt7996_sta_link *msta_link,
-                            u8 link_id, bool changed);
+int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct mt7996_sta *msta,
+                            struct ieee80211_vif *vif, u8 link_id,
+                            bool changed);
 int mt7996_set_channel(struct mt76_phy *mphy);
 int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag);
 int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif,