mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
wifi: mt76: Move RCU section in mt7996_mcu_add_rate_ctrl_fixed()
Since mt7996_mcu_set_fixed_field() can't be executed in a RCU critical
section, move RCU section in mt7996_mcu_add_rate_ctrl_fixed() and run
mt7996_mcu_set_fixed_field() 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-3-d46d15f9203c@kernel.org
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
committed by
Felix Fietkau
parent
c772cd726e
commit
28d519d0d4
@@ -1977,51 +1977,74 @@ error_unlock:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev,
|
mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct mt7996_sta *msta,
|
||||||
struct ieee80211_link_sta *link_sta,
|
struct ieee80211_vif *vif, u8 link_id)
|
||||||
struct mt7996_vif_link *link,
|
|
||||||
struct mt7996_sta_link *msta_link,
|
|
||||||
u8 link_id)
|
|
||||||
{
|
{
|
||||||
struct cfg80211_chan_def *chandef = &link->phy->mt76->chandef;
|
struct ieee80211_link_sta *link_sta;
|
||||||
struct cfg80211_bitrate_mask *mask = &link->bitrate_mask;
|
struct cfg80211_bitrate_mask mask;
|
||||||
enum nl80211_band band = chandef->chan->band;
|
struct mt7996_sta_link *msta_link;
|
||||||
struct mt7996_sta *msta = msta_link->sta;
|
struct mt7996_vif_link *link;
|
||||||
struct sta_phy_uni phy = {};
|
struct sta_phy_uni phy = {};
|
||||||
int ret, nrates = 0;
|
struct ieee80211_sta *sta;
|
||||||
|
int ret, nrates = 0, idx;
|
||||||
|
enum nl80211_band band;
|
||||||
|
bool has_he;
|
||||||
|
|
||||||
#define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \
|
#define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \
|
||||||
do { \
|
do { \
|
||||||
u8 i, gi = mask->control[band]._gi; \
|
u8 i, gi = mask.control[band]._gi; \
|
||||||
gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \
|
gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \
|
||||||
phy.sgi = gi; \
|
phy.sgi = gi; \
|
||||||
phy.he_ltf = mask->control[band].he_ltf; \
|
phy.he_ltf = mask.control[band].he_ltf; \
|
||||||
for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \
|
for (i = 0; i < ARRAY_SIZE(mask.control[band]._mcs); i++) { \
|
||||||
if (!mask->control[band]._mcs[i]) \
|
if (!mask.control[band]._mcs[i]) \
|
||||||
continue; \
|
continue; \
|
||||||
nrates += hweight16(mask->control[band]._mcs[i]); \
|
nrates += hweight16(mask.control[band]._mcs[i]); \
|
||||||
phy.mcs = ffs(mask->control[band]._mcs[i]) - 1; \
|
phy.mcs = ffs(mask.control[band]._mcs[i]) - 1; \
|
||||||
if (_ht) \
|
if (_ht) \
|
||||||
phy.mcs += 8 * i; \
|
phy.mcs += 8 * i; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
if (link_sta->he_cap.has_he) {
|
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;
|
||||||
|
|
||||||
|
band = link->phy->mt76->chandef.chan->band;
|
||||||
|
has_he = link_sta->he_cap.has_he;
|
||||||
|
mask = link->bitrate_mask;
|
||||||
|
idx = msta_link->wcid.idx;
|
||||||
|
|
||||||
|
if (has_he) {
|
||||||
__sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1);
|
__sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1);
|
||||||
} else if (link_sta->vht_cap.vht_supported) {
|
} else if (link_sta->vht_cap.vht_supported) {
|
||||||
__sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0);
|
__sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0);
|
||||||
} else if (link_sta->ht_cap.ht_supported) {
|
} else if (link_sta->ht_cap.ht_supported) {
|
||||||
__sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0);
|
__sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0);
|
||||||
} else {
|
} else {
|
||||||
nrates = hweight32(mask->control[band].legacy);
|
nrates = hweight32(mask.control[band].legacy);
|
||||||
phy.mcs = ffs(mask->control[band].legacy) - 1;
|
phy.mcs = ffs(mask.control[band].legacy) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
#undef __sta_phy_bitrate_mask_check
|
#undef __sta_phy_bitrate_mask_check
|
||||||
|
|
||||||
/* fall back to auto rate control */
|
/* fall back to auto rate control */
|
||||||
if (mask->control[band].gi == NL80211_TXRATE_DEFAULT_GI &&
|
if (mask.control[band].gi == NL80211_TXRATE_DEFAULT_GI &&
|
||||||
mask->control[band].he_gi == GENMASK(7, 0) &&
|
mask.control[band].he_gi == GENMASK(7, 0) &&
|
||||||
mask->control[band].he_ltf == GENMASK(7, 0) &&
|
mask.control[band].he_ltf == GENMASK(7, 0) &&
|
||||||
nrates != 1)
|
nrates != 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -2034,16 +2057,16 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* fixed GI */
|
/* fixed GI */
|
||||||
if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI ||
|
if (mask.control[band].gi != NL80211_TXRATE_DEFAULT_GI ||
|
||||||
mask->control[band].he_gi != GENMASK(7, 0)) {
|
mask.control[band].he_gi != GENMASK(7, 0)) {
|
||||||
u32 addr;
|
u32 addr;
|
||||||
|
|
||||||
/* firmware updates only TXCMD but doesn't take WTBL into
|
/* firmware updates only TXCMD but doesn't take WTBL into
|
||||||
* account, so driver should update here to reflect the
|
* account, so driver should update here to reflect the
|
||||||
* actual txrate hardware sends out.
|
* actual txrate hardware sends out.
|
||||||
*/
|
*/
|
||||||
addr = mt7996_mac_wtbl_lmac_addr(dev, msta_link->wcid.idx, 7);
|
addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 7);
|
||||||
if (link_sta->he_cap.has_he)
|
if (has_he)
|
||||||
mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi);
|
mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi);
|
||||||
else
|
else
|
||||||
mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);
|
mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);
|
||||||
@@ -2055,7 +2078,7 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* fixed HE_LTF */
|
/* fixed HE_LTF */
|
||||||
if (mask->control[band].he_ltf != GENMASK(7, 0)) {
|
if (mask.control[band].he_ltf != GENMASK(7, 0)) {
|
||||||
ret = mt7996_mcu_set_fixed_field(dev, msta, &phy, link_id,
|
ret = mt7996_mcu_set_fixed_field(dev, msta, &phy, link_id,
|
||||||
RATE_PARAM_FIXED_HE_LTF);
|
RATE_PARAM_FIXED_HE_LTF);
|
||||||
if (ret)
|
if (ret)
|
||||||
@@ -2063,6 +2086,11 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error_unlock:
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -2181,6 +2209,7 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
|
|||||||
struct mt7996_sta_link *msta_link,
|
struct mt7996_sta_link *msta_link,
|
||||||
u8 link_id, bool changed)
|
u8 link_id, bool changed)
|
||||||
{
|
{
|
||||||
|
struct mt7996_sta *msta = msta_link->sta;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -2207,8 +2236,7 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return mt7996_mcu_add_rate_ctrl_fixed(dev, link_sta, link, msta_link,
|
return mt7996_mcu_add_rate_ctrl_fixed(dev, msta, vif, link_id);
|
||||||
link_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
Reference in New Issue
Block a user