wifi: mt76: Move RCU section in mt7996_mcu_add_rate_ctrl()

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: 0762bdd302 ("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>
This commit is contained in:
Lorenzo Bianconi 2025-06-05 13:14:19 +02:00 committed by Felix Fietkau
parent 28d519d0d4
commit 3dd6f67c66
4 changed files with 45 additions and 27 deletions

View 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)

View 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;

View 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

View 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,