Split mt7925_mac_link_sta_add() into a host-only alloc half (allocates and publishes the wcid) and the STAREC/BSS half. The commit half now only raises STATE_NONE; the STATE_ASSOC transition moves to the add-links caller. Published links are freed by the unwind path, not here. Signed-off-by: Emery Hsin --- .../net/wireless/mediatek/mt76/mt7925/main.c | 132 +++++++++--------- 1 file changed, 63 insertions(+), 69 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c index 3af433d1e608..b497e904d4b5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c @@ -1048,33 +1048,23 @@ static void mt7925_mac_link_sta_free_wcid(struct mt76_dev *mdev, mt76_wcid_mask_clear(mdev->wcid_mask, wcid->idx); } -static int mt7925_mac_link_sta_add(struct mt76_dev *mdev, - struct ieee80211_vif *vif, - struct ieee80211_link_sta *link_sta, - struct mt792x_link_sta *mlink) +/* Allocate and publish the wcid only; no MCU command is sent. + * On failure the caller unwinds with mt7925_mac_link_sta_free_wcid(). + */ +static int mt7925_mac_link_sta_alloc(struct mt76_dev *mdev, + struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta, + struct mt792x_link_sta *mlink) { struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); - struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - struct ieee80211_bss_conf *link_conf; - struct mt792x_bss_conf *mconf; - u8 link_id = link_sta->link_id; - bool wcid_published = false; - bool is_secondary_link_sta; - struct mt792x_sta *msta; - struct mt76_wcid *wcid; - bool pm_woken = false; - int ret, idx; - - msta = (struct mt792x_sta *)link_sta->sta->drv_priv; - - if (WARN_ON_ONCE(!mlink)) - return -EINVAL; + struct mt792x_sta *msta = (struct mt792x_sta *)link_sta->sta->drv_priv; + struct mt76_wcid *wcid = &mlink->wcid; + int idx; idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1); if (idx < 0) return -ENOSPC; - mconf = mt792x_vif_to_link(mvif, link_id); mt76_wcid_init(&mlink->wcid, 0); mlink->wcid.sta = 1; mlink->wcid.idx = idx; @@ -1094,21 +1084,44 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev, wcid = &mlink->wcid; ewma_signal_init(&wcid->rssi); rcu_assign_pointer(dev->mt76.wcid[wcid->idx], wcid); - wcid_published = true; ewma_avg_signal_init(&mlink->avg_ack_signal); memset(mlink->airtime_ac, 0, sizeof(msta->deflink.airtime_ac)); + return 0; +} + +/* Program BSS_INFO and the STATE_NONE STAREC of one link. The wcid must + * already be allocated and published by mt7925_mac_link_sta_alloc(). + * On failure the caller unwinds the published state. + */ +static int mt7925_mac_link_sta_add(struct mt76_dev *mdev, + struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta, + struct mt792x_link_sta *mlink) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct ieee80211_bss_conf *link_conf; + struct mt792x_bss_conf *mconf; + u8 link_id = link_sta->link_id; + bool pm_woken = false; + int ret; + + if (WARN_ON_ONCE(!mlink)) + return -EINVAL; + + mconf = mt792x_vif_to_link(mvif, link_id); + ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm); if (ret) - goto out_wcid; + return ret; pm_woken = true; - mt7925_mac_wtbl_update(dev, idx, + mt7925_mac_wtbl_update(dev, mlink->wcid.idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); link_conf = mt792x_vif_to_bss_conf(vif, link_id); - is_secondary_link_sta = ieee80211_vif_is_mld(vif) && link_sta != mlink->pri_link; /* NAN_DATA (NDI) peers skip association - fill link_sta caps * from sband and push BSS_INFO with correct phymode + RLM. @@ -1134,45 +1147,16 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev, link_conf, link_sta, mconf->mt76.bmc_wcid ?: mlink_bc->wcid.idx, mlink->wcid.idx, - is_secondary_link_sta); + false); if (ret) goto out_pm; } - if (!is_secondary_link_sta) { - ret = mt7925_mcu_sta_update(dev, link_sta, vif, - mlink, true, - MT76_STA_INFO_STATE_NONE); - if (ret) - goto out_pm; - } else { - struct mt792x_link_sta *pri_mlink; - struct mt76_wcid *pri_wcid; - - /* alternative lookup via def_wcid */ - pri_wcid = mlink->wcid.def_wcid; - - pri_mlink = pri_wcid ? - container_of(pri_wcid, struct mt792x_link_sta, wcid) : - NULL; - - if (WARN_ON_ONCE(!pri_mlink)) { - ret = -EINVAL; - goto out_pm; - } - - ret = mt7925_mcu_sta_update(dev, mlink->pri_link, vif, - pri_mlink, true, - MT76_STA_INFO_STATE_ASSOC); - if (ret) - goto out_pm; - - ret = mt7925_mcu_sta_update(dev, link_sta, vif, - mlink, true, - MT76_STA_INFO_STATE_ASSOC); - if (ret) - goto out_pm; - } + /* Raise this link's STAREC to STATE_NONE, after its BSS_INFO. */ + ret = mt7925_mcu_sta_update(dev, link_sta, vif, mlink, true, + MT76_STA_INFO_STATE_NONE); + if (ret) + goto out_pm; mt76_connac_power_save_sched(&dev->mphy, &dev->pm); @@ -1181,9 +1165,6 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev, out_pm: if (pm_woken) mt76_connac_power_save_sched(&dev->mphy, &dev->pm); -out_wcid: - if (wcid_published) - mt7925_mac_link_sta_free_wcid(mdev, mlink); return ret; } @@ -1252,20 +1233,26 @@ mt7925_mac_sta_add_links(struct mt792x_dev *dev, struct ieee80211_vif *vif, mlink->wcid.def_wcid = &msta->deflink.wcid; link_sta = mt792x_sta_to_link_sta(vif, sta, link_id); - err = mt7925_mac_link_sta_add(&dev->mt76, vif, link_sta, mlink); + err = mt7925_mac_link_sta_alloc(&dev->mt76, vif, link_sta, + mlink); if (err) { if (!is_deflink) - kfree_rcu(mlink, rcu_head); + kfree(mlink); break; } - if (is_deflink) - msta->deflink_id = link_id; - rcu_assign_pointer(msta->link[link_id], mlink); msta->valid_links |= BIT(link_id); + if (is_deflink) + msta->deflink_id = link_id; + /* published into msta->link[]; let the unwind path free it */ added_links |= BIT(link_id); + + err = mt7925_mac_link_sta_add(&dev->mt76, vif, link_sta, + mlink); + if (err) + break; } if (err && added_links) @@ -1292,8 +1279,15 @@ int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, err = mt7925_mac_sta_add_links(dev, vif, sta, sta->valid_links); } else { - err = mt7925_mac_link_sta_add(mdev, vif, &sta->deflink, - &msta->deflink); + err = mt7925_mac_link_sta_alloc(mdev, vif, &sta->deflink, + &msta->deflink); + if (!err) { + err = mt7925_mac_link_sta_add(mdev, vif, &sta->deflink, + &msta->deflink); + if (err) + mt7925_mac_link_sta_free_wcid(mdev, + &msta->deflink); + } } return err; -- 2.45.2