mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-04 21:42:31 -04:00
wifi: mt76: Move RCU section in mt7996_mcu_set_fixed_field()
Since mt76_mcu_skb_send_msg() routine can't be executed in atomic context,
move RCU section in mt7996_mcu_set_fixed_field() 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-2-d46d15f9203c@kernel.org
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
committed by
Felix Fietkau
parent
a0c5eac918
commit
c772cd726e
@@ -2405,11 +2405,10 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
|
||||
IEEE80211_RC_BW_CHANGED))
|
||||
mt7996_mcu_add_rate_ctrl(dev, vif, link_conf,
|
||||
link_sta, link, msta_link,
|
||||
true);
|
||||
link_id, true);
|
||||
|
||||
if (changed & IEEE80211_RC_SMPS_CHANGED)
|
||||
mt7996_mcu_set_fixed_field(dev, link_sta, link,
|
||||
msta_link, NULL,
|
||||
mt7996_mcu_set_fixed_field(dev, msta, NULL, link_id,
|
||||
RATE_PARAM_MMPS_UPDATE);
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
@@ -1114,7 +1114,8 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
|
||||
err = mt7996_mcu_add_rate_ctrl(dev, vif, link_conf,
|
||||
link_sta, link,
|
||||
msta_link, false);
|
||||
msta_link, link_id,
|
||||
false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
@@ -1905,22 +1905,35 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
|
||||
MCU_WM_UNI_CMD(RA), true);
|
||||
}
|
||||
|
||||
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link,
|
||||
void *data, u32 field)
|
||||
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta,
|
||||
void *data, u8 link_id, u32 field)
|
||||
{
|
||||
struct sta_phy_uni *phy = data;
|
||||
struct mt7996_vif *mvif = msta->vif;
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct sta_rec_ra_fixed_uni *ra;
|
||||
struct sta_phy_uni *phy = data;
|
||||
struct mt76_vif_link *mlink;
|
||||
struct sk_buff *skb;
|
||||
int err = -ENODEV;
|
||||
struct tlv *tlv;
|
||||
|
||||
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
|
||||
rcu_read_lock();
|
||||
|
||||
mlink = rcu_dereference(mvif->mt76.link[link_id]);
|
||||
if (!mlink)
|
||||
goto error_unlock;
|
||||
|
||||
msta_link = rcu_dereference(msta->link[link_id]);
|
||||
if (!msta_link)
|
||||
goto error_unlock;
|
||||
|
||||
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, mlink,
|
||||
&msta_link->wcid,
|
||||
MT7996_STA_UPDATE_MAX_SIZE);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
if (IS_ERR(skb)) {
|
||||
err = PTR_ERR(skb);
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra));
|
||||
ra = (struct sta_rec_ra_fixed_uni *)tlv;
|
||||
@@ -1935,27 +1948,45 @@ int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
|
||||
if (phy)
|
||||
ra->phy = *phy;
|
||||
break;
|
||||
case RATE_PARAM_MMPS_UPDATE:
|
||||
case RATE_PARAM_MMPS_UPDATE: {
|
||||
struct ieee80211_sta *sta = wcid_to_sta(&msta_link->wcid);
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
|
||||
link_sta = rcu_dereference(sta->link[link_id]);
|
||||
if (!link_sta) {
|
||||
dev_kfree_skb(skb);
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
ra->mmps_mode = mt7996_mcu_get_mmps_mode(link_sta->smps_mode);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ra->field = cpu_to_le32(field);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
|
||||
error_unlock:
|
||||
rcu_read_unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link)
|
||||
struct mt7996_sta_link *msta_link,
|
||||
u8 link_id)
|
||||
{
|
||||
struct cfg80211_chan_def *chandef = &link->phy->mt76->chandef;
|
||||
struct cfg80211_bitrate_mask *mask = &link->bitrate_mask;
|
||||
enum nl80211_band band = chandef->chan->band;
|
||||
struct mt7996_sta *msta = msta_link->sta;
|
||||
struct sta_phy_uni phy = {};
|
||||
int ret, nrates = 0;
|
||||
|
||||
@@ -1996,8 +2027,7 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev,
|
||||
|
||||
/* fixed single rate */
|
||||
if (nrates == 1) {
|
||||
ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
|
||||
msta_link, &phy,
|
||||
ret = mt7996_mcu_set_fixed_field(dev, msta, &phy, link_id,
|
||||
RATE_PARAM_FIXED_MCS);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -2018,8 +2048,7 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev,
|
||||
else
|
||||
mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);
|
||||
|
||||
ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
|
||||
msta_link, &phy,
|
||||
ret = mt7996_mcu_set_fixed_field(dev, msta, &phy, link_id,
|
||||
RATE_PARAM_FIXED_GI);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -2027,8 +2056,7 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev,
|
||||
|
||||
/* fixed HE_LTF */
|
||||
if (mask->control[band].he_ltf != GENMASK(7, 0)) {
|
||||
ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
|
||||
msta_link, &phy,
|
||||
ret = mt7996_mcu_set_fixed_field(dev, msta, &phy, link_id,
|
||||
RATE_PARAM_FIXED_HE_LTF);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -2150,7 +2178,8 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link, bool changed)
|
||||
struct mt7996_sta_link *msta_link,
|
||||
u8 link_id, bool changed)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
@@ -2178,7 +2207,8 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt7996_mcu_add_rate_ctrl_fixed(dev, link_sta, link, msta_link);
|
||||
return mt7996_mcu_add_rate_ctrl_fixed(dev, link_sta, link, msta_link,
|
||||
link_id);
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -625,18 +625,16 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link, bool changed);
|
||||
struct mt7996_sta_link *msta_link,
|
||||
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,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
|
||||
void *data, u16 version);
|
||||
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link,
|
||||
void *data, u32 field);
|
||||
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta,
|
||||
void *data, u8 link_id, u32 field);
|
||||
int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);
|
||||
int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len);
|
||||
int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num);
|
||||
|
||||
Reference in New Issue
Block a user