summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2026-10-06 22:59:26 +0200
committerFelix Fietkau <nbd@nbd.name>2026-10-07 12:50:44 +0200
commit72f050d4b04e40f450573ffb95cb4717c8bbfefb (patch)
tree452602df38b6343ee06038de4c47efb381e2980a /drivers/net
parent854c8d4358272ad1204e9436996dec264fe334b1 (diff)
downloadlinux-next-72f050d4b04e40f450573ffb95cb4717c8bbfefb.tar.gz
linux-next-72f050d4b04e40f450573ffb95cb4717c8bbfefb.zip
wifi: mt76: mt7996: keep 4-address and decap state per station
mac80211 reports 4-address mode and decap offload once per station, through sta_set_4addr and sta_set_decap_offload. mt7996_sta_set_4addr() and mt7996_sta_set_decap_offload() set MT_WCID_FLAG_4ADDR and MT_WCID_FLAG_HDR_TRANS only on the links that exist at that moment, but the hardware keeps header translation per link. A link that is added later starts without the flags, and a link that is removed at that time keeps its old flags when it comes back, so the firmware gets the wrong to_ds/from_ds pair for that link. Keep both states in the station, and apply them to a link when the callbacks run, when the link is set up and when it comes back. Fixes: f520eceacd24 ("wifi: mt76: mt7996: Add mt7996_mac_sta_change_links callback") Fixes: e8c819df0243 ("wifi: mt76: mt7996: Destroy active sta links in mt7996_mac_sta_remove()") Link: https://patch.msgid.link/20261006205936.669125-17-nbd@nbd.name Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/main.c29
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h2
2 files changed, 19 insertions, 12 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index d868e9641334..bba5a8c6dec8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1155,6 +1155,16 @@ mt7996_sta_deflink_set(struct ieee80211_sta *sta, unsigned int link_id,
mt7996_sta_init_txq_wcid(sta, idx);
}
+static void
+mt7996_sta_link_hdr_trans_set(struct mt7996_sta *msta,
+ struct mt7996_sta_link *msta_link)
+{
+ assign_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags,
+ test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid_flags));
+ assign_bit(MT_WCID_FLAG_HDR_TRANS, &msta_link->wcid.flags,
+ test_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid_flags));
+}
+
static bool
mt7996_sta_deflink_busy(struct mt7996_dev *dev, struct mt7996_sta *msta)
{
@@ -1261,6 +1271,8 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev,
if (link_sta->sta->tdls)
set_bit(MT_WCID_FLAG_TDLS_PEER, &msta_link->wcid.flags);
+ mt7996_sta_link_hdr_trans_set(msta, msta_link);
+
ewma_avg_signal_init(&msta_link->avg_ack_signal);
ewma_signal_init(&msta_link->wcid.rssi);
@@ -1381,6 +1393,7 @@ mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
msta_link = mt76_dereference(msta->link[link_id], &dev->mt76);
if (msta_link) {
msta_link->wcid.link_valid = true;
+ mt7996_sta_link_hdr_trans_set(msta, msta_link);
if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED)
mt7996_sta_deflink_set(sta, link_id,
msta_link->wcid.idx);
@@ -2166,6 +2179,7 @@ static void mt7996_sta_set_4addr(struct ieee80211_hw *hw,
mutex_lock(&dev->mt76.mutex);
+ assign_bit(MT_WCID_FLAG_4ADDR, &msta->wcid_flags, enabled);
for_each_sta_active_link(vif, sta, link_sta, link_id) {
struct mt7996_sta_link *msta_link;
struct mt7996_vif_link *link;
@@ -2178,11 +2192,7 @@ static void mt7996_sta_set_4addr(struct ieee80211_hw *hw,
if (!msta_link)
continue;
- if (enabled)
- set_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags);
- else
- clear_bit(MT_WCID_FLAG_4ADDR, &msta_link->wcid.flags);
-
+ mt7996_sta_link_hdr_trans_set(msta, msta_link);
if (!msta_link->wcid.sta)
continue;
@@ -2212,6 +2222,7 @@ static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw,
mutex_lock(&dev->mt76.mutex);
+ assign_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid_flags, enabled);
for_each_sta_active_link(vif, sta, link_sta, link_id) {
struct mt7996_sta_link *msta_link;
struct mt7996_vif_link *link;
@@ -2224,13 +2235,7 @@ static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw,
if (!msta_link)
continue;
- if (enabled)
- set_bit(MT_WCID_FLAG_HDR_TRANS,
- &msta_link->wcid.flags);
- else
- clear_bit(MT_WCID_FLAG_HDR_TRANS,
- &msta_link->wcid.flags);
-
+ mt7996_sta_link_hdr_trans_set(msta, msta_link);
if (!msta_link->wcid.sta)
continue;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 03fc0e7fd4f1..949e659b8e2d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -269,6 +269,8 @@ struct mt7996_sta {
u8 deflink_id;
u8 seclink_id;
+ unsigned long wcid_flags;
+
struct mt7996_vif *vif;
};