Skip to content

Commit c772cd7

Browse files
LorenzoBianconinbd168
authored andcommitted
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: 0762bdd ("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>
1 parent a0c5eac commit c772cd7

File tree

4 files changed

+57
-29
lines changed

4 files changed

+57
-29
lines changed

drivers/net/wireless/mediatek/mt76/mt7996/mac.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2405,11 +2405,10 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
24052405
IEEE80211_RC_BW_CHANGED))
24062406
mt7996_mcu_add_rate_ctrl(dev, vif, link_conf,
24072407
link_sta, link, msta_link,
2408-
true);
2408+
link_id, true);
24092409

24102410
if (changed & IEEE80211_RC_SMPS_CHANGED)
2411-
mt7996_mcu_set_fixed_field(dev, link_sta, link,
2412-
msta_link, NULL,
2411+
mt7996_mcu_set_fixed_field(dev, msta, NULL, link_id,
24132412
RATE_PARAM_MMPS_UPDATE);
24142413

24152414
spin_lock_bh(&dev->mt76.sta_poll_lock);

drivers/net/wireless/mediatek/mt76/mt7996/main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1114,7 +1114,8 @@ mt7996_mac_sta_event(struct mt7996_dev *dev, struct ieee80211_vif *vif,
11141114

11151115
err = mt7996_mcu_add_rate_ctrl(dev, vif, link_conf,
11161116
link_sta, link,
1117-
msta_link, false);
1117+
msta_link, link_id,
1118+
false);
11181119
if (err)
11191120
return err;
11201121

drivers/net/wireless/mediatek/mt76/mt7996/mcu.c

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1905,22 +1905,35 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
19051905
MCU_WM_UNI_CMD(RA), true);
19061906
}
19071907

1908-
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
1909-
struct ieee80211_link_sta *link_sta,
1910-
struct mt7996_vif_link *link,
1911-
struct mt7996_sta_link *msta_link,
1912-
void *data, u32 field)
1908+
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta,
1909+
void *data, u8 link_id, u32 field)
19131910
{
1914-
struct sta_phy_uni *phy = data;
1911+
struct mt7996_vif *mvif = msta->vif;
1912+
struct mt7996_sta_link *msta_link;
19151913
struct sta_rec_ra_fixed_uni *ra;
1914+
struct sta_phy_uni *phy = data;
1915+
struct mt76_vif_link *mlink;
19161916
struct sk_buff *skb;
1917+
int err = -ENODEV;
19171918
struct tlv *tlv;
19181919

1919-
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
1920+
rcu_read_lock();
1921+
1922+
mlink = rcu_dereference(mvif->mt76.link[link_id]);
1923+
if (!mlink)
1924+
goto error_unlock;
1925+
1926+
msta_link = rcu_dereference(msta->link[link_id]);
1927+
if (!msta_link)
1928+
goto error_unlock;
1929+
1930+
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, mlink,
19201931
&msta_link->wcid,
19211932
MT7996_STA_UPDATE_MAX_SIZE);
1922-
if (IS_ERR(skb))
1923-
return PTR_ERR(skb);
1933+
if (IS_ERR(skb)) {
1934+
err = PTR_ERR(skb);
1935+
goto error_unlock;
1936+
}
19241937

19251938
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra));
19261939
ra = (struct sta_rec_ra_fixed_uni *)tlv;
@@ -1935,27 +1948,45 @@ int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
19351948
if (phy)
19361949
ra->phy = *phy;
19371950
break;
1938-
case RATE_PARAM_MMPS_UPDATE:
1951+
case RATE_PARAM_MMPS_UPDATE: {
1952+
struct ieee80211_sta *sta = wcid_to_sta(&msta_link->wcid);
1953+
struct ieee80211_link_sta *link_sta;
1954+
1955+
link_sta = rcu_dereference(sta->link[link_id]);
1956+
if (!link_sta) {
1957+
dev_kfree_skb(skb);
1958+
goto error_unlock;
1959+
}
1960+
19391961
ra->mmps_mode = mt7996_mcu_get_mmps_mode(link_sta->smps_mode);
19401962
break;
1963+
}
19411964
default:
19421965
break;
19431966
}
19441967
ra->field = cpu_to_le32(field);
19451968

1969+
rcu_read_unlock();
1970+
19461971
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
19471972
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
1973+
error_unlock:
1974+
rcu_read_unlock();
1975+
1976+
return err;
19481977
}
19491978

19501979
static int
19511980
mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev,
19521981
struct ieee80211_link_sta *link_sta,
19531982
struct mt7996_vif_link *link,
1954-
struct mt7996_sta_link *msta_link)
1983+
struct mt7996_sta_link *msta_link,
1984+
u8 link_id)
19551985
{
19561986
struct cfg80211_chan_def *chandef = &link->phy->mt76->chandef;
19571987
struct cfg80211_bitrate_mask *mask = &link->bitrate_mask;
19581988
enum nl80211_band band = chandef->chan->band;
1989+
struct mt7996_sta *msta = msta_link->sta;
19591990
struct sta_phy_uni phy = {};
19601991
int ret, nrates = 0;
19611992

@@ -1996,8 +2027,7 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev,
19962027

19972028
/* fixed single rate */
19982029
if (nrates == 1) {
1999-
ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
2000-
msta_link, &phy,
2030+
ret = mt7996_mcu_set_fixed_field(dev, msta, &phy, link_id,
20012031
RATE_PARAM_FIXED_MCS);
20022032
if (ret)
20032033
return ret;
@@ -2018,17 +2048,15 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev,
20182048
else
20192049
mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);
20202050

2021-
ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
2022-
msta_link, &phy,
2051+
ret = mt7996_mcu_set_fixed_field(dev, msta, &phy, link_id,
20232052
RATE_PARAM_FIXED_GI);
20242053
if (ret)
20252054
return ret;
20262055
}
20272056

20282057
/* fixed HE_LTF */
20292058
if (mask->control[band].he_ltf != GENMASK(7, 0)) {
2030-
ret = mt7996_mcu_set_fixed_field(dev, link_sta, link,
2031-
msta_link, &phy,
2059+
ret = mt7996_mcu_set_fixed_field(dev, msta, &phy, link_id,
20322060
RATE_PARAM_FIXED_HE_LTF);
20332061
if (ret)
20342062
return ret;
@@ -2150,7 +2178,8 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
21502178
struct ieee80211_bss_conf *link_conf,
21512179
struct ieee80211_link_sta *link_sta,
21522180
struct mt7996_vif_link *link,
2153-
struct mt7996_sta_link *msta_link, bool changed)
2181+
struct mt7996_sta_link *msta_link,
2182+
u8 link_id, bool changed)
21542183
{
21552184
struct sk_buff *skb;
21562185
int ret;
@@ -2178,7 +2207,8 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
21782207
if (ret)
21792208
return ret;
21802209

2181-
return mt7996_mcu_add_rate_ctrl_fixed(dev, link_sta, link, msta_link);
2210+
return mt7996_mcu_add_rate_ctrl_fixed(dev, link_sta, link, msta_link,
2211+
link_id);
21822212
}
21832213

21842214
static int

drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -625,18 +625,16 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
625625
struct ieee80211_bss_conf *link_conf,
626626
struct ieee80211_link_sta *link_sta,
627627
struct mt7996_vif_link *link,
628-
struct mt7996_sta_link *msta_link, bool changed);
628+
struct mt7996_sta_link *msta_link,
629+
u8 link_id, bool changed);
629630
int mt7996_set_channel(struct mt76_phy *mphy);
630631
int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag);
631632
int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif,
632633
struct ieee80211_bss_conf *link_conf);
633634
int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
634635
void *data, u16 version);
635-
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
636-
struct ieee80211_link_sta *link_sta,
637-
struct mt7996_vif_link *link,
638-
struct mt7996_sta_link *msta_link,
639-
void *data, u32 field);
636+
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta,
637+
void *data, u8 link_id, u32 field);
640638
int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);
641639
int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len);
642640
int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num);

0 commit comments

Comments
 (0)