Skip to content

Commit dd82a9e

Browse files
LorenzoBianconinbd168
authored andcommitted
wifi: mt76: mt7996: Rely on mt7996_sta_link in sta_add/sta_remove callbacks
Generalize mt7996_mac_sta_add() and mt7996_mac_sta_remove() routines to deal with mt7996_sta_link structure. This is a preliminary patch to introduce MLO support for MT7996 driver. Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com> Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com> Co-developed-by: Peter Chiu <chui-hao.chiu@mediatek.com> Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com> Co-developed-by: Shayne Chen <shayne.chen@mediatek.com> Signed-off-by: Shayne Chen <shayne.chen@mediatek.com> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/20250311-mt7996-mlo-v2-7-31df6972519b@kernel.org Signed-off-by: Felix Fietkau <nbd@nbd.name>
1 parent e5d944b commit dd82a9e

File tree

2 files changed

+143
-50
lines changed

2 files changed

+143
-50
lines changed

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

Lines changed: 139 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -816,59 +816,164 @@ mt7996_channel_switch_beacon(struct ieee80211_hw *hw,
816816
}
817817

818818
static int
819-
mt7996_mac_sta_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
820-
struct ieee80211_sta *sta)
819+
mt7996_mac_sta_init_link(struct mt7996_dev *dev, struct ieee80211_vif *vif,
820+
struct mt7996_vif_link *link,
821+
struct ieee80211_sta *sta, unsigned int link_id)
821822
{
822-
struct mt76_dev *mdev = mphy->dev;
823-
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
824823
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
825-
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
826-
struct mt7996_sta_link *msta_link = &msta->deflink;
827-
struct mt7996_vif_link *link = &mvif->deflink;
828-
u8 band_idx = mphy->band_idx;
829-
int i, idx, ret = 0;
824+
struct mt7996_phy *phy = link->phy;
825+
struct mt7996_sta_link *msta_link;
826+
int idx;
830827

831-
mutex_lock(&mdev->mutex);
828+
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);
829+
if (idx < 0)
830+
return -ENOSPC;
831+
832+
if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED) {
833+
int i;
834+
835+
msta_link = &msta->deflink;
836+
msta->deflink_id = link_id;
837+
838+
for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
839+
struct mt76_txq *mtxq;
840+
841+
if (!sta->txq[i])
842+
continue;
832843

833-
idx = mt76_wcid_alloc(mdev->wcid_mask, MT7996_WTBL_STA);
834-
if (idx < 0) {
835-
ret = -ENOSPC;
836-
goto unlock;
844+
mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
845+
mtxq->wcid = idx;
846+
}
847+
} else {
848+
msta_link = kzalloc(sizeof(*msta_link), GFP_KERNEL);
849+
if (!msta_link)
850+
return -ENOMEM;
837851
}
838852

839-
msta->vif = mvif;
840853
INIT_LIST_HEAD(&msta_link->rc_list);
841854
INIT_LIST_HEAD(&msta_link->wcid.poll_list);
842855
msta_link->sta = msta;
843856
msta_link->wcid.sta = 1;
844857
msta_link->wcid.idx = idx;
845-
msta_link->wcid.phy_idx = band_idx;
858+
msta_link->wcid.link_id = link_id;
859+
860+
ewma_avg_signal_init(&msta_link->avg_ack_signal);
861+
ewma_signal_init(&msta_link->wcid.rssi);
846862

847-
for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
848-
struct mt76_txq *mtxq;
863+
rcu_assign_pointer(msta->link[link_id], msta_link);
849864

850-
if (!sta->txq[i])
865+
mt7996_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
866+
mt7996_mcu_add_sta(dev, vif, &link->mt76, sta, CONN_STATE_DISCONNECT,
867+
true);
868+
869+
rcu_assign_pointer(dev->mt76.wcid[idx], &msta_link->wcid);
870+
mt76_wcid_init(&msta_link->wcid, phy->mt76->band_idx);
871+
872+
return 0;
873+
}
874+
875+
static void
876+
mt7996_mac_sta_deinit_link(struct mt7996_dev *dev,
877+
struct mt7996_sta_link *msta_link)
878+
{
879+
int i;
880+
881+
for (i = 0; i < ARRAY_SIZE(msta_link->wcid.aggr); i++)
882+
mt76_rx_aggr_stop(&dev->mt76, &msta_link->wcid, i);
883+
884+
mt7996_mac_wtbl_update(dev, msta_link->wcid.idx,
885+
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
886+
887+
spin_lock_bh(&dev->mt76.sta_poll_lock);
888+
if (!list_empty(&msta_link->wcid.poll_list))
889+
list_del_init(&msta_link->wcid.poll_list);
890+
if (!list_empty(&msta_link->rc_list))
891+
list_del_init(&msta_link->rc_list);
892+
spin_unlock_bh(&dev->mt76.sta_poll_lock);
893+
894+
mt76_wcid_cleanup(&dev->mt76, &msta_link->wcid);
895+
mt76_wcid_mask_clear(dev->mt76.wcid_mask, msta_link->wcid.idx);
896+
}
897+
898+
static void
899+
mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_sta *sta,
900+
unsigned long links)
901+
{
902+
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
903+
struct mt76_dev *mdev = &dev->mt76;
904+
unsigned int link_id;
905+
906+
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
907+
struct mt7996_sta_link *msta_link = NULL;
908+
909+
msta_link = rcu_replace_pointer(msta->link[link_id], msta_link,
910+
lockdep_is_held(&mdev->mutex));
911+
if (!msta_link)
851912
continue;
852913

853-
mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
854-
mtxq->wcid = idx;
914+
mt7996_mac_sta_deinit_link(dev, msta_link);
915+
if (msta->deflink_id == link_id) {
916+
msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
917+
continue;
918+
}
919+
920+
kfree_rcu(msta_link, rcu_head);
855921
}
922+
}
856923

857-
ewma_avg_signal_init(&msta_link->avg_ack_signal);
858-
ewma_signal_init(&msta_link->wcid.rssi);
924+
static int
925+
mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
926+
struct ieee80211_sta *sta, unsigned long new_links)
927+
{
928+
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
929+
unsigned int link_id;
930+
int err;
859931

860-
mt7996_mac_wtbl_update(dev, idx,
861-
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
862-
mt7996_mcu_add_sta(dev, vif, &link->mt76, sta, CONN_STATE_DISCONNECT,
863-
true);
932+
for_each_set_bit(link_id, &new_links, IEEE80211_MLD_MAX_NUM_LINKS) {
933+
struct mt7996_vif_link *link;
934+
935+
if (rcu_access_pointer(msta->link[link_id]))
936+
continue;
937+
938+
link = mt7996_vif_link(dev, vif, link_id);
939+
if (!link)
940+
goto error_unlink;
941+
942+
err = mt7996_mac_sta_init_link(dev, vif, link, sta, link_id);
943+
if (err)
944+
goto error_unlink;
945+
}
946+
947+
return 0;
948+
949+
error_unlink:
950+
mt7996_mac_sta_remove_links(dev, sta, new_links);
951+
952+
return err;
953+
}
954+
955+
static int
956+
mt7996_mac_sta_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
957+
struct ieee80211_sta *sta)
958+
{
959+
struct mt76_dev *mdev = mphy->dev;
960+
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
961+
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
962+
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
963+
unsigned long links = sta->mlo ? sta->valid_links : BIT(0);
964+
int err;
965+
966+
mutex_lock(&mdev->mutex);
967+
968+
msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
969+
msta->vif = mvif;
970+
err = mt7996_mac_sta_add_links(dev, vif, sta, links);
971+
if (!err)
972+
mphy->num_sta++;
864973

865-
rcu_assign_pointer(mdev->wcid[idx], &msta_link->wcid);
866-
mt76_wcid_init(&msta_link->wcid, band_idx);
867-
mphy->num_sta++;
868-
unlock:
869974
mutex_unlock(&mdev->mutex);
870975

871-
return ret;
976+
return err;
872977
}
873978

874979
static int
@@ -922,27 +1027,11 @@ mt7996_mac_sta_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
9221027
{
9231028
struct mt76_dev *mdev = mphy->dev;
9241029
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
925-
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
926-
struct mt7996_sta_link *msta_link = &msta->deflink;
927-
int i, idx = msta_link->wcid.idx;
1030+
unsigned long links = sta->mlo ? sta->valid_links : BIT(0);
9281031

9291032
mutex_lock(&mdev->mutex);
9301033

931-
for (i = 0; i < ARRAY_SIZE(msta_link->wcid.aggr); i++)
932-
mt76_rx_aggr_stop(mdev, &msta_link->wcid, i);
933-
934-
mt7996_mac_wtbl_update(dev, msta_link->wcid.idx,
935-
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
936-
937-
spin_lock_bh(&mdev->sta_poll_lock);
938-
if (!list_empty(&msta_link->wcid.poll_list))
939-
list_del_init(&msta_link->wcid.poll_list);
940-
if (!list_empty(&msta_link->rc_list))
941-
list_del_init(&msta_link->rc_list);
942-
spin_unlock_bh(&mdev->sta_poll_lock);
943-
944-
mt76_wcid_cleanup(mdev, &msta_link->wcid);
945-
mt76_wcid_mask_clear(mdev->wcid_mask, idx);
1034+
mt7996_mac_sta_remove_links(dev, sta, links);
9461035
mphy->num_sta--;
9471036

9481037
mutex_unlock(&mdev->mutex);

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,14 @@ struct mt7996_sta_link {
204204
u8 flowid_mask;
205205
struct mt7996_twt_flow flow[MT7996_MAX_STA_TWT_AGRT];
206206
} twt;
207+
208+
struct rcu_head rcu_head;
207209
};
208210

209211
struct mt7996_sta {
210212
struct mt7996_sta_link deflink; /* must be first */
213+
struct mt7996_sta_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
214+
u8 deflink_id;
211215

212216
struct mt7996_vif *vif;
213217
};

0 commit comments

Comments
 (0)