* [PATCH v2 01/15] wifi: mt76: mt7915: move sta_poll_list and sta_poll_lock in mt76_dev
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 02/15] wifi: mt76: mt7603: rely on shared sta_poll_list and sta_poll_lock Lorenzo Bianconi
` (13 subsequent siblings)
14 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
sta_poll_list and sta_poll_lock are used by most of the drivers, so move
them in mt76_dev structure.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mac80211.c | 2 +
drivers/net/wireless/mediatek/mt76/mt76.h | 3 ++
.../net/wireless/mediatek/mt76/mt7915/init.c | 2 -
.../net/wireless/mediatek/mt76/mt7915/mac.c | 47 ++++++++++---------
.../net/wireless/mediatek/mt76/mt7915/main.c | 12 ++---
.../wireless/mediatek/mt76/mt7915/mt7915.h | 2 -
6 files changed, 36 insertions(+), 32 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 467afef98ba2..952f4cbd3ce8 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -660,6 +660,8 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
idr_init(&dev->rx_token);
INIT_LIST_HEAD(&dev->wcid_list);
+ INIT_LIST_HEAD(&dev->sta_poll_list);
+ spin_lock_init(&dev->sta_poll_lock);
INIT_LIST_HEAD(&dev->txwi_cache);
INIT_LIST_HEAD(&dev->rxwi_cache);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 6b07b8fafec2..5eae2e666ff6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -823,6 +823,9 @@ struct mt76_dev {
struct mt76_wcid __rcu *wcid[MT76_N_WCIDS];
struct list_head wcid_list;
+ struct list_head sta_poll_list;
+ spinlock_t sta_poll_lock;
+
u32 rev;
struct tasklet_struct pre_tbtt_tasklet;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index ac2049f49bb3..90c883c7fe05 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -1177,9 +1177,7 @@ int mt7915_register_device(struct mt7915_dev *dev)
INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7915_mac_work);
INIT_LIST_HEAD(&dev->sta_rc_list);
- INIT_LIST_HEAD(&dev->sta_poll_list);
INIT_LIST_HEAD(&dev->twt_list);
- spin_lock_init(&dev->sta_poll_lock);
init_waitqueue_head(&dev->reset_wait);
INIT_WORK(&dev->reset_work, mt7915_mac_reset_work);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index 7df8d95fc3fb..f29ab70d3ce2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -105,9 +105,9 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
LIST_HEAD(sta_poll_list);
int i;
- spin_lock_bh(&dev->sta_poll_lock);
- list_splice_init(&dev->sta_poll_list, &sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
+ list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
rcu_read_lock();
@@ -118,15 +118,15 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
s8 rssi[4];
u8 bw;
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&sta_poll_list)) {
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
break;
}
msta = list_first_entry(&sta_poll_list,
struct mt7915_sta, poll_list);
list_del_init(&msta->poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
idx = msta->wcid.idx;
@@ -326,10 +326,11 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb,
if (status->wcid) {
msta = container_of(status->wcid, struct mt7915_sta, wcid);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ list_add_tail(&msta->poll_list,
+ &dev->mt76.sta_poll_list);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
status->freq = mphy->chandef.chan->center_freq;
@@ -892,10 +893,11 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
msta = container_of(wcid, struct mt7915_sta, wcid);
sta = container_of((void *)msta, struct ieee80211_sta,
drv_priv);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&mdev->sta_poll_lock);
if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ list_add_tail(&msta->poll_list,
+ &mdev->sta_poll_list);
+ spin_unlock_bh(&mdev->sta_poll_lock);
}
}
@@ -987,10 +989,11 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
continue;
msta = container_of(wcid, struct mt7915_sta, wcid);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&mdev->sta_poll_lock);
if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ list_add_tail(&msta->poll_list,
+ &mdev->sta_poll_list);
+ spin_unlock_bh(&mdev->sta_poll_lock);
continue;
}
@@ -1081,10 +1084,10 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
if (!wcid->sta)
goto out;
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
out:
rcu_read_unlock();
@@ -2010,7 +2013,7 @@ void mt7915_mac_sta_rc_work(struct work_struct *work)
u32 changed;
LIST_HEAD(list);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
list_splice_init(&dev->sta_rc_list, &list);
while (!list_empty(&list)) {
@@ -2018,7 +2021,7 @@ void mt7915_mac_sta_rc_work(struct work_struct *work)
list_del_init(&msta->rc_list);
changed = msta->changed;
msta->changed = 0;
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
@@ -2031,10 +2034,10 @@ void mt7915_mac_sta_rc_work(struct work_struct *work)
if (changed & IEEE80211_RC_SMPS_CHANGED)
mt7915_mcu_add_smps(dev, vif, sta);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
}
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
void mt7915_mac_work(struct work_struct *work)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 2ada2806de66..805b4522a813 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -308,10 +308,10 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
mutex_unlock(&dev->mt76.mutex);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
}
@@ -715,12 +715,12 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)
mt7915_mac_twt_teardown_flow(dev, msta, i);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&mdev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
if (!list_empty(&msta->rc_list))
list_del_init(&msta->rc_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&mdev->sta_poll_lock);
}
static void mt7915_tx(struct ieee80211_hw *hw,
@@ -1074,11 +1074,11 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)
struct mt7915_dev *dev = msta->vif->phy->dev;
u32 *changed = data;
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
msta->changed |= *changed;
if (list_empty(&msta->rc_list))
list_add_tail(&msta->rc_list, &dev->sta_rc_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
static void mt7915_sta_rc_update(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index b3ead3530740..f8ff190e9c4e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -328,9 +328,7 @@ struct mt7915_dev {
#endif
struct list_head sta_rc_list;
- struct list_head sta_poll_list;
struct list_head twt_list;
- spinlock_t sta_poll_lock;
u32 hw_pattern;
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v2 02/15] wifi: mt76: mt7603: rely on shared sta_poll_list and sta_poll_lock
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 01/15] wifi: mt76: mt7915: move sta_poll_list and sta_poll_lock in mt76_dev Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 03/15] wifi: mt76: mt7615: " Lorenzo Bianconi
` (12 subsequent siblings)
14 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
Rely on sta_poll_list and sta_poll_lock fields in mt76_dev structure
and get rid of private copies.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
.../net/wireless/mediatek/mt76/mt7603/init.c | 2 --
.../net/wireless/mediatek/mt76/mt7603/mac.c | 18 +++++++++---------
.../net/wireless/mediatek/mt76/mt7603/main.c | 8 ++++----
.../net/wireless/mediatek/mt76/mt7603/mt7603.h | 3 ---
4 files changed, 13 insertions(+), 18 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
index 9a2e632d577a..0762de3ce5ac 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
@@ -500,8 +500,6 @@ int mt7603_register_device(struct mt7603_dev *dev)
bus_ops->rmw = mt7603_rmw;
dev->mt76.bus = bus_ops;
- INIT_LIST_HEAD(&dev->sta_poll_list);
- spin_lock_init(&dev->sta_poll_lock);
spin_lock_init(&dev->ps_lock);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7603_mac_work);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
index 12e0af52082a..ac8a67e10a4d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
@@ -412,16 +412,16 @@ void mt7603_mac_sta_poll(struct mt7603_dev *dev)
while (1) {
bool clear = false;
- spin_lock_bh(&dev->sta_poll_lock);
- if (list_empty(&dev->sta_poll_list)) {
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
+ if (list_empty(&dev->mt76.sta_poll_list)) {
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
break;
}
- msta = list_first_entry(&dev->sta_poll_list, struct mt7603_sta,
- poll_list);
+ msta = list_first_entry(&dev->mt76.sta_poll_list,
+ struct mt7603_sta, poll_list);
list_del_init(&msta->poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
addr = mt7603_wtbl4_addr(msta->wcid.idx);
for (i = 0; i < 4; i++) {
@@ -1268,9 +1268,9 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data)
sta = wcid_to_sta(wcid);
if (list_empty(&msta->poll_list)) {
- spin_lock_bh(&dev->sta_poll_lock);
- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
+ list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
if (mt7603_mac_add_txs_skb(dev, msta, pid, txs_data))
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
index ca50feb0b3a9..2affa62caf2b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -100,10 +100,10 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
mutex_lock(&dev->mt76.mutex);
dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx);
@@ -388,10 +388,10 @@ mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
mt7603_filter_tx(dev, wcid->idx, true);
spin_unlock_bh(&dev->ps_lock);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&mdev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&mdev->sta_poll_lock);
mt7603_wtbl_clear(dev, wcid->idx);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
index 7c3be596da09..689922d133e7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
@@ -110,9 +110,6 @@ struct mt7603_dev {
u32 rxfilter;
- struct list_head sta_poll_list;
- spinlock_t sta_poll_lock;
-
struct mt7603_sta global_sta;
u32 agc0, agc3;
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v2 03/15] wifi: mt76: mt7615: rely on shared sta_poll_list and sta_poll_lock
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 01/15] wifi: mt76: mt7915: move sta_poll_list and sta_poll_lock in mt76_dev Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 02/15] wifi: mt76: mt7603: rely on shared sta_poll_list and sta_poll_lock Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 04/15] wifi: mt76: mt7996: " Lorenzo Bianconi
` (11 subsequent siblings)
14 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
Rely on sta_poll_list and sta_poll_lock fields in mt76_dev structure
and get rid of private copies.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
.../net/wireless/mediatek/mt76/mt7615/init.c | 2 --
.../net/wireless/mediatek/mt76/mt7615/mac.c | 23 ++++++++++---------
.../net/wireless/mediatek/mt76/mt7615/main.c | 8 +++----
.../wireless/mediatek/mt76/mt7615/mt7615.h | 3 ---
4 files changed, 16 insertions(+), 20 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index 621e69f07e3c..155931978ed8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -626,8 +626,6 @@ void mt7615_init_device(struct mt7615_dev *dev)
INIT_DELAYED_WORK(&dev->coredump.work, mt7615_coredump_work);
skb_queue_head_init(&dev->phy.scan_event_list);
skb_queue_head_init(&dev->coredump.msg_list);
- INIT_LIST_HEAD(&dev->sta_poll_list);
- spin_lock_init(&dev->sta_poll_lock);
init_waitqueue_head(&dev->reset_wait);
init_waitqueue_head(&dev->phy.roc_wait);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
index 415b5ff3ee4f..0fc6d7765f83 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -387,10 +387,11 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
struct mt7615_sta *msta;
msta = container_of(status->wcid, struct mt7615_sta, wcid);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ list_add_tail(&msta->poll_list,
+ &dev->mt76.sta_poll_list);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
if (mt76_is_mmio(&dev->mt76) && (rxd0 & csum_mask) == csum_mask &&
@@ -905,9 +906,9 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev)
int i;
INIT_LIST_HEAD(&sta_poll_list);
- spin_lock_bh(&dev->sta_poll_lock);
- list_splice_init(&dev->sta_poll_list, &sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
+ list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
while (!list_empty(&sta_poll_list)) {
bool clear = false;
@@ -915,9 +916,9 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev)
msta = list_first_entry(&sta_poll_list, struct mt7615_sta,
poll_list);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
list_del_init(&msta->poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
addr = mt7615_mac_wtbl_addr(dev, msta->wcid.idx) + 19 * 4;
@@ -1542,10 +1543,10 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
msta = container_of(wcid, struct mt7615_sta, wcid);
sta = wcid_to_sta(wcid);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
if (mt7615_mac_add_txs_skb(dev, msta, pid, txs_data))
goto out;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index ab4c1b4478aa..2a5462bd54c2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -274,10 +274,10 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
mt7615_mutex_release(dev);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
}
@@ -677,10 +677,10 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
mt7615_mcu_add_bss_info(phy, vif, sta, false);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&mdev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&mdev->sta_poll_lock);
mt76_connac_power_save_sched(phy->mt76, &dev->pm);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
index 0381c53bc96a..7386495f8299 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
@@ -262,9 +262,6 @@ struct mt7615_dev {
wait_queue_head_t reset_wait;
u32 reset_state;
- struct list_head sta_poll_list;
- spinlock_t sta_poll_lock;
-
struct {
u8 n_pulses;
u32 period;
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v2 04/15] wifi: mt76: mt7996: rely on shared sta_poll_list and sta_poll_lock
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
` (2 preceding siblings ...)
2023-06-09 8:15 ` [PATCH v2 03/15] wifi: mt76: mt7615: " Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 05/15] wifi: mt76: mt7921: " Lorenzo Bianconi
` (10 subsequent siblings)
14 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
Rely on sta_poll_list and sta_poll_lock fields in mt76_dev structure
and get rid of private copies.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
.../net/wireless/mediatek/mt76/mt7996/init.c | 2 -
.../net/wireless/mediatek/mt76/mt7996/mac.c | 40 ++++++++++---------
.../net/wireless/mediatek/mt76/mt7996/main.c | 12 +++---
.../wireless/mediatek/mt76/mt7996/mt7996.h | 2 -
4 files changed, 27 insertions(+), 29 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
index f1b48cdda58f..8f3536dbe2bb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
@@ -853,9 +853,7 @@ int mt7996_register_device(struct mt7996_dev *dev)
INIT_WORK(&dev->rc_work, mt7996_mac_sta_rc_work);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7996_mac_work);
INIT_LIST_HEAD(&dev->sta_rc_list);
- INIT_LIST_HEAD(&dev->sta_poll_list);
INIT_LIST_HEAD(&dev->twt_list);
- spin_lock_init(&dev->sta_poll_lock);
init_waitqueue_head(&dev->reset_wait);
INIT_WORK(&dev->reset_work, mt7996_mac_reset_work);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 740d08e9d5e5..18249572cb2e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -111,9 +111,9 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
LIST_HEAD(sta_poll_list);
int i;
- spin_lock_bh(&dev->sta_poll_lock);
- list_splice_init(&dev->sta_poll_list, &sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
+ list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
rcu_read_lock();
@@ -124,15 +124,15 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
s8 rssi[4];
u8 bw;
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&sta_poll_list)) {
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
break;
}
msta = list_first_entry(&sta_poll_list,
struct mt7996_sta, poll_list);
list_del_init(&msta->poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
idx = msta->wcid.idx;
@@ -681,10 +681,11 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
struct mt7996_sta *msta;
msta = container_of(status->wcid, struct mt7996_sta, wcid);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ list_add_tail(&msta->poll_list,
+ &dev->mt76.sta_poll_list);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
status->freq = mphy->chandef.chan->center_freq;
@@ -1286,10 +1287,11 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
continue;
msta = container_of(wcid, struct mt7996_sta, wcid);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&mdev->sta_poll_lock);
if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ list_add_tail(&msta->poll_list,
+ &mdev->sta_poll_list);
+ spin_unlock_bh(&mdev->sta_poll_lock);
continue;
}
@@ -1494,10 +1496,10 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
if (!wcid->sta)
goto out;
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
out:
rcu_read_unlock();
@@ -2340,7 +2342,7 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
u32 changed;
LIST_HEAD(list);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
list_splice_init(&dev->sta_rc_list, &list);
while (!list_empty(&list)) {
@@ -2348,7 +2350,7 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
list_del_init(&msta->rc_list);
changed = msta->changed;
msta->changed = 0;
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
@@ -2360,10 +2362,10 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
/* TODO: smps change */
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
}
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
void mt7996_mac_work(struct work_struct *work)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index c7917e301c87..ecac04066fda 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -262,10 +262,10 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
mutex_unlock(&dev->mt76.mutex);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
}
@@ -667,12 +667,12 @@ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)
mt7996_mac_twt_teardown_flow(dev, msta, i);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&mdev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
if (!list_empty(&msta->rc_list))
list_del_init(&msta->rc_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&mdev->sta_poll_lock);
}
static void mt7996_tx(struct ieee80211_hw *hw,
@@ -982,11 +982,11 @@ static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta)
struct mt7996_dev *dev = msta->vif->phy->dev;
u32 *changed = data;
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
msta->changed |= *changed;
if (list_empty(&msta->rc_list))
list_add_tail(&msta->rc_list, &dev->sta_rc_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
static void mt7996_sta_rc_update(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index c9f0e541abe4..9be7a5f80f4d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -270,9 +270,7 @@ struct mt7996_dev {
#endif
struct list_head sta_rc_list;
- struct list_head sta_poll_list;
struct list_head twt_list;
- spinlock_t sta_poll_lock;
u32 hw_pattern;
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v2 05/15] wifi: mt76: mt7921: rely on shared sta_poll_list and sta_poll_lock
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
` (3 preceding siblings ...)
2023-06-09 8:15 ` [PATCH v2 04/15] wifi: mt76: mt7996: " Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 06/15] wifi: mt76: mt7915: move poll_list in mt76_wcid Lorenzo Bianconi
` (9 subsequent siblings)
14 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
Rely on sta_poll_list and sta_poll_lock fields in mt76_dev structure
and get rid of private copies.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
.../net/wireless/mediatek/mt76/mt7921/init.c | 2 --
.../net/wireless/mediatek/mt76/mt7921/mac.c | 32 ++++++++++---------
.../net/wireless/mediatek/mt76/mt7921/main.c | 8 ++---
.../wireless/mediatek/mt76/mt7921/mt7921.h | 3 --
4 files changed, 21 insertions(+), 24 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index e929f6eb65ce..cdb4478f04d0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -392,8 +392,6 @@ int mt7921_register_device(struct mt7921_dev *dev)
#endif
skb_queue_head_init(&dev->phy.scan_event_list);
skb_queue_head_init(&dev->coredump.msg_list);
- INIT_LIST_HEAD(&dev->sta_poll_list);
- spin_lock_init(&dev->sta_poll_lock);
INIT_WORK(&dev->reset_work, mt7921_mac_reset_work);
INIT_WORK(&dev->init_work, mt7921_init_work);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index bde73859b5da..d81d78ac5c91 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -68,9 +68,9 @@ static void mt7921_mac_sta_poll(struct mt7921_dev *dev)
s8 rssi[4];
int i;
- spin_lock_bh(&dev->sta_poll_lock);
- list_splice_init(&dev->sta_poll_list, &sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
+ list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
while (true) {
bool clear = false;
@@ -78,15 +78,15 @@ static void mt7921_mac_sta_poll(struct mt7921_dev *dev)
u16 idx;
u8 bw;
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&sta_poll_list)) {
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
break;
}
msta = list_first_entry(&sta_poll_list,
struct mt7921_sta, poll_list);
list_del_init(&msta->poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
idx = msta->wcid.idx;
addr = mt7921_mac_wtbl_lmac_addr(idx, MT_WTBL_AC0_CTT_OFFSET);
@@ -280,10 +280,11 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
if (status->wcid) {
msta = container_of(status->wcid, struct mt7921_sta, wcid);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ list_add_tail(&msta->poll_list,
+ &dev->mt76.sta_poll_list);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
mt7921_get_status_freq_info(dev, mphy, status, chfreq);
@@ -566,10 +567,10 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
if (!wcid->sta)
goto out;
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
out:
rcu_read_unlock();
@@ -647,10 +648,11 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
continue;
msta = container_of(wcid, struct mt7921_sta, wcid);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&mdev->sta_poll_lock);
if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ list_add_tail(&msta->poll_list,
+ &mdev->sta_poll_list);
+ spin_unlock_bh(&mdev->sta_poll_lock);
continue;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index 0c9a472bc81a..ffbe48f33d49 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -357,10 +357,10 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw,
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
mt7921_mutex_release(dev);
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
}
@@ -843,10 +843,10 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
mvif->ctx);
}
- spin_lock_bh(&dev->sta_poll_lock);
+ spin_lock_bh(&dev->mt76.sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
- spin_unlock_bh(&dev->sta_poll_lock);
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
index 9640cc033300..ef1fe4d9ab99 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
@@ -303,9 +303,6 @@ struct mt7921_dev {
bool hw_init_done:1;
bool fw_assert:1;
- struct list_head sta_poll_list;
- spinlock_t sta_poll_lock;
-
struct work_struct init_work;
u8 fw_debug;
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v2 06/15] wifi: mt76: mt7915: move poll_list in mt76_wcid
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
` (4 preceding siblings ...)
2023-06-09 8:15 ` [PATCH v2 05/15] wifi: mt76: mt7921: " Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 07/15] wifi: mt76: mt7603: rely on shared poll_list field Lorenzo Bianconi
` (8 subsequent siblings)
14 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
poll_list field is used by most of the drivers, so move it in mt76_wcid
structure.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt76.h | 2 ++
.../net/wireless/mediatek/mt76/mt7915/mac.c | 20 +++++++++----------
.../net/wireless/mediatek/mt76/mt7915/main.c | 12 +++++------
.../wireless/mediatek/mt76/mt7915/mt7915.h | 1 -
4 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 5eae2e666ff6..997bd722b045 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -336,6 +336,8 @@ struct mt76_wcid {
struct idr pktid;
struct mt76_sta_stats stats;
+
+ struct list_head poll_list;
};
struct mt76_txq {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index f29ab70d3ce2..b499ab7d95f8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -124,8 +124,8 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
break;
}
msta = list_first_entry(&sta_poll_list,
- struct mt7915_sta, poll_list);
- list_del_init(&msta->poll_list);
+ struct mt7915_sta, wcid.poll_list);
+ list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
idx = msta->wcid.idx;
@@ -327,8 +327,8 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb,
if (status->wcid) {
msta = container_of(status->wcid, struct mt7915_sta, wcid);
spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list,
+ if (list_empty(&msta->wcid.poll_list))
+ list_add_tail(&msta->wcid.poll_list,
&dev->mt76.sta_poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
@@ -894,8 +894,8 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
sta = container_of((void *)msta, struct ieee80211_sta,
drv_priv);
spin_lock_bh(&mdev->sta_poll_lock);
- if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list,
+ if (list_empty(&msta->wcid.poll_list))
+ list_add_tail(&msta->wcid.poll_list,
&mdev->sta_poll_list);
spin_unlock_bh(&mdev->sta_poll_lock);
}
@@ -990,8 +990,8 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
msta = container_of(wcid, struct mt7915_sta, wcid);
spin_lock_bh(&mdev->sta_poll_lock);
- if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list,
+ if (list_empty(&msta->wcid.poll_list))
+ list_add_tail(&msta->wcid.poll_list,
&mdev->sta_poll_list);
spin_unlock_bh(&mdev->sta_poll_lock);
continue;
@@ -1085,8 +1085,8 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
goto out;
spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list);
+ if (list_empty(&msta->wcid.poll_list))
+ list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
out:
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 805b4522a813..cf1ed8632925 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -248,7 +248,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
idx = MT7915_WTBL_RESERVED - mvif->mt76.idx;
INIT_LIST_HEAD(&mvif->sta.rc_list);
- INIT_LIST_HEAD(&mvif->sta.poll_list);
+ INIT_LIST_HEAD(&mvif->sta.wcid.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.phy_idx = ext_phy;
mvif->sta.wcid.hw_key_idx = -1;
@@ -309,8 +309,8 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&dev->mt76.mutex);
spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (!list_empty(&msta->poll_list))
- list_del_init(&msta->poll_list);
+ if (!list_empty(&msta->wcid.poll_list))
+ list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
@@ -680,7 +680,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
return -ENOSPC;
INIT_LIST_HEAD(&msta->rc_list);
- INIT_LIST_HEAD(&msta->poll_list);
+ INIT_LIST_HEAD(&msta->wcid.poll_list);
msta->vif = mvif;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
@@ -716,8 +716,8 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
mt7915_mac_twt_teardown_flow(dev, msta, i);
spin_lock_bh(&mdev->sta_poll_lock);
- if (!list_empty(&msta->poll_list))
- list_del_init(&msta->poll_list);
+ if (!list_empty(&msta->wcid.poll_list))
+ list_del_init(&msta->wcid.poll_list);
if (!list_empty(&msta->rc_list))
list_del_init(&msta->rc_list);
spin_unlock_bh(&mdev->sta_poll_lock);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index f8ff190e9c4e..0ebd44fa5f5f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -129,7 +129,6 @@ struct mt7915_sta {
struct mt7915_vif *vif;
- struct list_head poll_list;
struct list_head rc_list;
u32 airtime_ac[8];
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v2 07/15] wifi: mt76: mt7603: rely on shared poll_list field
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
` (5 preceding siblings ...)
2023-06-09 8:15 ` [PATCH v2 06/15] wifi: mt76: mt7915: move poll_list in mt76_wcid Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 08/15] wifi: mt76: mt7615: " Lorenzo Bianconi
` (7 subsequent siblings)
14 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
Rely on poll_list field in mt76_wcid structure and get rid of
private copy.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 8 ++++----
drivers/net/wireless/mediatek/mt76/mt7603/main.c | 12 ++++++------
drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h | 1 -
3 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
index ac8a67e10a4d..de11557eb04c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
@@ -419,8 +419,8 @@ void mt7603_mac_sta_poll(struct mt7603_dev *dev)
}
msta = list_first_entry(&dev->mt76.sta_poll_list,
- struct mt7603_sta, poll_list);
- list_del_init(&msta->poll_list);
+ struct mt7603_sta, wcid.poll_list);
+ list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
addr = mt7603_wtbl4_addr(msta->wcid.idx);
@@ -1267,9 +1267,9 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data)
msta = container_of(wcid, struct mt7603_sta, wcid);
sta = wcid_to_sta(wcid);
- if (list_empty(&msta->poll_list)) {
+ if (list_empty(&msta->wcid.poll_list)) {
spin_lock_bh(&dev->mt76.sta_poll_lock);
- list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list);
+ list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
index 2affa62caf2b..36f287bbddd1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -66,7 +66,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
idx = MT7603_WTBL_RESERVED - 1 - mvif->idx;
dev->mt76.vif_mask |= BIT_ULL(mvif->idx);
- INIT_LIST_HEAD(&mvif->sta.poll_list);
+ INIT_LIST_HEAD(&mvif->sta.wcid.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.hw_key_idx = -1;
mt76_packet_id_init(&mvif->sta.wcid);
@@ -101,8 +101,8 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (!list_empty(&msta->poll_list))
- list_del_init(&msta->poll_list);
+ if (!list_empty(&msta->wcid.poll_list))
+ list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mutex_lock(&dev->mt76.mutex);
@@ -351,7 +351,7 @@ mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (idx < 0)
return -ENOSPC;
- INIT_LIST_HEAD(&msta->poll_list);
+ INIT_LIST_HEAD(&msta->wcid.poll_list);
__skb_queue_head_init(&msta->psq);
msta->ps = ~0;
msta->smps = ~0;
@@ -389,8 +389,8 @@ mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
spin_unlock_bh(&dev->ps_lock);
spin_lock_bh(&mdev->sta_poll_lock);
- if (!list_empty(&msta->poll_list))
- list_del_init(&msta->poll_list);
+ if (!list_empty(&msta->wcid.poll_list))
+ list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&mdev->sta_poll_lock);
mt7603_wtbl_clear(dev, wcid->idx);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
index 689922d133e7..354b189862f7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
@@ -64,7 +64,6 @@ struct mt7603_sta {
struct mt7603_vif *vif;
- struct list_head poll_list;
u32 tx_airtime_ac[4];
struct sk_buff_head psq;
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v2 08/15] wifi: mt76: mt7615: rely on shared poll_list field
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
` (6 preceding siblings ...)
2023-06-09 8:15 ` [PATCH v2 07/15] wifi: mt76: mt7603: rely on shared poll_list field Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 09/15] wifi: mt76: mt7996: " Lorenzo Bianconi
` (6 subsequent siblings)
14 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
Rely on poll_list field in mt76_wcid structure and get rid of
private copy.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 12 ++++++------
drivers/net/wireless/mediatek/mt76/mt7615/main.c | 12 ++++++------
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 1 -
3 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
index 0fc6d7765f83..f46b884d2905 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -388,8 +388,8 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
msta = container_of(status->wcid, struct mt7615_sta, wcid);
spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list,
+ if (list_empty(&msta->wcid.poll_list))
+ list_add_tail(&msta->wcid.poll_list,
&dev->mt76.sta_poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
@@ -914,10 +914,10 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev)
bool clear = false;
msta = list_first_entry(&sta_poll_list, struct mt7615_sta,
- poll_list);
+ wcid.poll_list);
spin_lock_bh(&dev->mt76.sta_poll_lock);
- list_del_init(&msta->poll_list);
+ list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
addr = mt7615_mac_wtbl_addr(dev, msta->wcid.idx) + 19 * 4;
@@ -1544,8 +1544,8 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
sta = wcid_to_sta(wcid);
spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list);
+ if (list_empty(&msta->wcid.poll_list))
+ list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
if (mt7615_mac_add_txs_skb(dev, msta, pid, txs_data))
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index 2a5462bd54c2..5c342d85b8d8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -222,7 +222,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
idx = MT7615_WTBL_RESERVED - mvif->mt76.idx;
- INIT_LIST_HEAD(&mvif->sta.poll_list);
+ INIT_LIST_HEAD(&mvif->sta.wcid.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
mvif->sta.wcid.hw_key_idx = -1;
@@ -275,8 +275,8 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
mt7615_mutex_release(dev);
spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (!list_empty(&msta->poll_list))
- list_del_init(&msta->poll_list);
+ if (!list_empty(&msta->wcid.poll_list))
+ list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
@@ -629,7 +629,7 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (idx < 0)
return -ENOSPC;
- INIT_LIST_HEAD(&msta->poll_list);
+ INIT_LIST_HEAD(&msta->wcid.poll_list);
msta->vif = mvif;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
@@ -678,8 +678,8 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
mt7615_mcu_add_bss_info(phy, vif, sta, false);
spin_lock_bh(&mdev->sta_poll_lock);
- if (!list_empty(&msta->poll_list))
- list_del_init(&msta->poll_list);
+ if (!list_empty(&msta->wcid.poll_list))
+ list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&mdev->sta_poll_lock);
mt76_connac_power_save_sched(phy->mt76, &dev->pm);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
index 7386495f8299..6a7c14dbf72e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
@@ -125,7 +125,6 @@ struct mt7615_sta {
struct mt7615_vif *vif;
- struct list_head poll_list;
u32 airtime_ac[8];
struct ieee80211_tx_rate rates[4];
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v2 09/15] wifi: mt76: mt7996: rely on shared poll_list field
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
` (7 preceding siblings ...)
2023-06-09 8:15 ` [PATCH v2 08/15] wifi: mt76: mt7615: " Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 10/15] wifi: mt76: mt7921: " Lorenzo Bianconi
` (5 subsequent siblings)
14 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
Rely on poll_list field in mt76_wcid structure and get rid of
private copy.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 16 ++++++++--------
drivers/net/wireless/mediatek/mt76/mt7996/main.c | 12 ++++++------
.../net/wireless/mediatek/mt76/mt7996/mt7996.h | 1 -
3 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 18249572cb2e..5e1f26d3c5ad 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -130,8 +130,8 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
break;
}
msta = list_first_entry(&sta_poll_list,
- struct mt7996_sta, poll_list);
- list_del_init(&msta->poll_list);
+ struct mt7996_sta, wcid.poll_list);
+ list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
idx = msta->wcid.idx;
@@ -682,8 +682,8 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
msta = container_of(status->wcid, struct mt7996_sta, wcid);
spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list,
+ if (list_empty(&msta->wcid.poll_list))
+ list_add_tail(&msta->wcid.poll_list,
&dev->mt76.sta_poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
@@ -1288,8 +1288,8 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
msta = container_of(wcid, struct mt7996_sta, wcid);
spin_lock_bh(&mdev->sta_poll_lock);
- if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list,
+ if (list_empty(&msta->wcid.poll_list))
+ list_add_tail(&msta->wcid.poll_list,
&mdev->sta_poll_list);
spin_unlock_bh(&mdev->sta_poll_lock);
continue;
@@ -1497,8 +1497,8 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
goto out;
spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list);
+ if (list_empty(&msta->wcid.poll_list))
+ list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
out:
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index ecac04066fda..1a5d646631a6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -200,7 +200,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
idx = MT7996_WTBL_RESERVED - mvif->mt76.idx;
INIT_LIST_HEAD(&mvif->sta.rc_list);
- INIT_LIST_HEAD(&mvif->sta.poll_list);
+ INIT_LIST_HEAD(&mvif->sta.wcid.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.phy_idx = band_idx;
mvif->sta.wcid.hw_key_idx = -1;
@@ -263,8 +263,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&dev->mt76.mutex);
spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (!list_empty(&msta->poll_list))
- list_del_init(&msta->poll_list);
+ if (!list_empty(&msta->wcid.poll_list))
+ list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
@@ -632,7 +632,7 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
return -ENOSPC;
INIT_LIST_HEAD(&msta->rc_list);
- INIT_LIST_HEAD(&msta->poll_list);
+ INIT_LIST_HEAD(&msta->wcid.poll_list);
msta->vif = mvif;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
@@ -668,8 +668,8 @@ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
mt7996_mac_twt_teardown_flow(dev, msta, i);
spin_lock_bh(&mdev->sta_poll_lock);
- if (!list_empty(&msta->poll_list))
- list_del_init(&msta->poll_list);
+ if (!list_empty(&msta->wcid.poll_list))
+ list_del_init(&msta->wcid.poll_list);
if (!list_empty(&msta->rc_list))
list_del_init(&msta->rc_list);
spin_unlock_bh(&mdev->sta_poll_lock);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 9be7a5f80f4d..e1ab38bf9118 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -95,7 +95,6 @@ struct mt7996_sta {
struct mt7996_vif *vif;
- struct list_head poll_list;
struct list_head rc_list;
u32 airtime_ac[8];
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v2 10/15] wifi: mt76: mt7921: rely on shared poll_list field
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
` (8 preceding siblings ...)
2023-06-09 8:15 ` [PATCH v2 09/15] wifi: mt76: mt7996: " Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 11/15] wifi: mt76: move ampdu_state in mt76_wcid Lorenzo Bianconi
` (4 subsequent siblings)
14 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
Rely on poll_list field in mt76_wcid structure and get rid of
private copy.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 16 ++++++++--------
drivers/net/wireless/mediatek/mt76/mt7921/main.c | 12 ++++++------
.../net/wireless/mediatek/mt76/mt7921/mt7921.h | 1 -
3 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index d81d78ac5c91..561590713e0b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -84,8 +84,8 @@ static void mt7921_mac_sta_poll(struct mt7921_dev *dev)
break;
}
msta = list_first_entry(&sta_poll_list,
- struct mt7921_sta, poll_list);
- list_del_init(&msta->poll_list);
+ struct mt7921_sta, wcid.poll_list);
+ list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
idx = msta->wcid.idx;
@@ -281,8 +281,8 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
if (status->wcid) {
msta = container_of(status->wcid, struct mt7921_sta, wcid);
spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list,
+ if (list_empty(&msta->wcid.poll_list))
+ list_add_tail(&msta->wcid.poll_list,
&dev->mt76.sta_poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
@@ -568,8 +568,8 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
goto out;
spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list, &dev->mt76.sta_poll_list);
+ if (list_empty(&msta->wcid.poll_list))
+ list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
out:
@@ -649,8 +649,8 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
msta = container_of(wcid, struct mt7921_sta, wcid);
spin_lock_bh(&mdev->sta_poll_lock);
- if (list_empty(&msta->poll_list))
- list_add_tail(&msta->poll_list,
+ if (list_empty(&msta->wcid.poll_list))
+ list_add_tail(&msta->wcid.poll_list,
&mdev->sta_poll_list);
spin_unlock_bh(&mdev->sta_poll_lock);
continue;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index ffbe48f33d49..2512c1c1fb89 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -313,7 +313,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
idx = MT7921_WTBL_RESERVED - mvif->mt76.idx;
- INIT_LIST_HEAD(&mvif->sta.poll_list);
+ INIT_LIST_HEAD(&mvif->sta.wcid.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
mvif->sta.wcid.hw_key_idx = -1;
@@ -358,8 +358,8 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw,
mt7921_mutex_release(dev);
spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (!list_empty(&msta->poll_list))
- list_del_init(&msta->poll_list);
+ if (!list_empty(&msta->wcid.poll_list))
+ list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
@@ -765,7 +765,7 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (idx < 0)
return -ENOSPC;
- INIT_LIST_HEAD(&msta->poll_list);
+ INIT_LIST_HEAD(&msta->wcid.poll_list);
msta->vif = mvif;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
@@ -844,8 +844,8 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
}
spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (!list_empty(&msta->poll_list))
- list_del_init(&msta->poll_list);
+ if (!list_empty(&msta->wcid.poll_list))
+ list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
index ef1fe4d9ab99..bd2c4190b77e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
@@ -150,7 +150,6 @@ struct mt7921_sta {
struct mt7921_vif *vif;
- struct list_head poll_list;
u32 airtime_ac[8];
int ack_signal;
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v2 11/15] wifi: mt76: move ampdu_state in mt76_wcid
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
` (9 preceding siblings ...)
2023-06-09 8:15 ` [PATCH v2 10/15] wifi: mt76: mt7921: " Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 12/15] mt76: connac: move more mt7921/mt7915 mac shared code in connac lib Lorenzo Bianconi
` (3 subsequent siblings)
14 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
ampdu_state field is used by most of the drivers, so move it in
mt76_wcid structure.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7915/main.c | 6 +++---
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 1 -
drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7921/main.c | 6 +++---
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h | 1 -
drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7996/main.c | 6 +++---
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 1 -
10 files changed, 13 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 997bd722b045..878cebb8a4e9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -316,6 +316,7 @@ struct mt76_wcid {
int inactive_count;
struct rate_info rate;
+ unsigned long ampdu_state;
u16 idx;
u8 hw_key_idx;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index b499ab7d95f8..5c2c054b31fb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -863,7 +863,7 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
return;
msta = (struct mt7915_sta *)sta->drv_priv;
- if (!test_and_set_bit(tid, &msta->ampdu_state))
+ if (!test_and_set_bit(tid, &msta->wcid.ampdu_state))
ieee80211_start_tx_ba_session(sta, tid, 0);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index cf1ed8632925..f2b4a99bd142 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -802,16 +802,16 @@ mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
mtxq->aggr = false;
- clear_bit(tid, &msta->ampdu_state);
+ clear_bit(tid, &msta->wcid.ampdu_state);
ret = mt7915_mcu_add_tx_ba(dev, params, false);
break;
case IEEE80211_AMPDU_TX_START:
- set_bit(tid, &msta->ampdu_state);
+ set_bit(tid, &msta->wcid.ampdu_state);
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
break;
case IEEE80211_AMPDU_TX_STOP_CONT:
mtxq->aggr = false;
- clear_bit(tid, &msta->ampdu_state);
+ clear_bit(tid, &msta->wcid.ampdu_state);
ret = mt7915_mcu_add_tx_ba(dev, params, false);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index 0ebd44fa5f5f..ca01199afd11 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -137,7 +137,6 @@ struct mt7915_sta {
unsigned long changed;
unsigned long jiffies;
- unsigned long ampdu_state;
struct mt76_connac_sta_key_conf bip;
struct {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index 561590713e0b..f0e67e62abc2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -531,7 +531,7 @@ static void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
return;
msta = (struct mt7921_sta *)sta->drv_priv;
- if (!test_and_set_bit(tid, &msta->ampdu_state))
+ if (!test_and_set_bit(tid, &msta->wcid.ampdu_state))
ieee80211_start_tx_ba_session(sta, tid, 0);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index 2512c1c1fb89..ecfa3ef70902 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -955,16 +955,16 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
mtxq->aggr = false;
- clear_bit(tid, &msta->ampdu_state);
+ clear_bit(tid, &msta->wcid.ampdu_state);
mt7921_mcu_uni_tx_ba(dev, params, false);
break;
case IEEE80211_AMPDU_TX_START:
- set_bit(tid, &msta->ampdu_state);
+ set_bit(tid, &msta->wcid.ampdu_state);
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
break;
case IEEE80211_AMPDU_TX_STOP_CONT:
mtxq->aggr = false;
- clear_bit(tid, &msta->ampdu_state);
+ clear_bit(tid, &msta->wcid.ampdu_state);
mt7921_mcu_uni_tx_ba(dev, params, false);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
index bd2c4190b77e..d4dfbbdb5f27 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
@@ -156,7 +156,6 @@ struct mt7921_sta {
struct ewma_avg_signal avg_ack_signal;
unsigned long last_txs;
- unsigned long ampdu_state;
struct mt76_connac_sta_key_conf bip;
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 5e1f26d3c5ad..753e9c7b1199 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -1199,7 +1199,7 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
return;
msta = (struct mt7996_sta *)sta->drv_priv;
- if (!test_and_set_bit(tid, &msta->ampdu_state))
+ if (!test_and_set_bit(tid, &msta->wcid.ampdu_state))
ieee80211_start_tx_ba_session(sta, tid, 0);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 1a5d646631a6..2d20de7c8916 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -752,16 +752,16 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
mtxq->aggr = false;
- clear_bit(tid, &msta->ampdu_state);
+ clear_bit(tid, &msta->wcid.ampdu_state);
ret = mt7996_mcu_add_tx_ba(dev, params, false);
break;
case IEEE80211_AMPDU_TX_START:
- set_bit(tid, &msta->ampdu_state);
+ set_bit(tid, &msta->wcid.ampdu_state);
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
break;
case IEEE80211_AMPDU_TX_STOP_CONT:
mtxq->aggr = false;
- clear_bit(tid, &msta->ampdu_state);
+ clear_bit(tid, &msta->wcid.ampdu_state);
ret = mt7996_mcu_add_tx_ba(dev, params, false);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index e1ab38bf9118..829973abc28d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -103,7 +103,6 @@ struct mt7996_sta {
unsigned long changed;
unsigned long jiffies;
- unsigned long ampdu_state;
struct mt76_connac_sta_key_conf bip;
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v2 12/15] mt76: connac: move more mt7921/mt7915 mac shared code in connac lib
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
` (10 preceding siblings ...)
2023-06-09 8:15 ` [PATCH v2 11/15] wifi: mt76: move ampdu_state in mt76_wcid Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 13/15] wifi: mt76: move rate info in mt76_vif Lorenzo Bianconi
` (2 subsequent siblings)
14 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
Move the following routines in mt76-connac lib since they are shared
between mt7915 and mt7921:
- mt76_connac2_tx_check_aggr
- mt76_connac2_txwi_free
- mt76_connac2_tx_token_put
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
.../net/wireless/mediatek/mt76/mt76_connac.h | 5 +
.../wireless/mediatek/mt76/mt76_connac_mac.c | 82 +++++++++++++++++
.../net/wireless/mediatek/mt76/mt7915/init.c | 2 +-
.../net/wireless/mediatek/mt76/mt7915/mac.c | 91 +------------------
.../wireless/mediatek/mt76/mt7915/mt7915.h | 1 -
.../net/wireless/mediatek/mt76/mt7921/mac.c | 62 +------------
.../wireless/mediatek/mt76/mt7921/mt7921.h | 4 -
.../net/wireless/mediatek/mt76/mt7921/pci.c | 2 +-
.../wireless/mediatek/mt76/mt7921/pci_mac.c | 16 +---
9 files changed, 96 insertions(+), 169 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
index 15653b274f83..68bdeada1421 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
@@ -409,5 +409,10 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
struct mt76_rx_status *status,
struct ieee80211_supported_band *sband,
__le32 *rxv, u8 *mode);
+void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi);
+void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t,
+ struct ieee80211_sta *sta,
+ struct list_head *free_list);
+void mt76_connac2_tx_token_put(struct mt76_dev *dev);
#endif /* __MT76_CONNAC_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
index d39a3cc5e381..74e7997d2c9f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
@@ -1112,3 +1112,85 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
return 0;
}
EXPORT_SYMBOL_GPL(mt76_connac2_mac_fill_rx_rate);
+
+void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
+{
+ struct mt76_wcid *wcid;
+ u16 fc, tid;
+ u32 val;
+
+ if (!sta ||
+ !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
+ return;
+
+ tid = le32_get_bits(txwi[1], MT_TXD1_TID);
+ if (tid >= 6) /* skip VO queue */
+ return;
+
+ val = le32_to_cpu(txwi[2]);
+ fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
+ FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
+ if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
+ return;
+
+ wcid = (struct mt76_wcid *)sta->drv_priv;
+ if (!test_and_set_bit(tid, &wcid->ampdu_state))
+ ieee80211_start_tx_ba_session(sta, tid, 0);
+}
+EXPORT_SYMBOL_GPL(mt76_connac2_tx_check_aggr);
+
+void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t,
+ struct ieee80211_sta *sta,
+ struct list_head *free_list)
+{
+ struct mt76_wcid *wcid;
+ __le32 *txwi;
+ u16 wcid_idx;
+
+ mt76_connac_txp_skb_unmap(dev, t);
+ if (!t->skb)
+ goto out;
+
+ txwi = (__le32 *)mt76_get_txwi_ptr(dev, t);
+ if (sta) {
+ wcid = (struct mt76_wcid *)sta->drv_priv;
+ wcid_idx = wcid->idx;
+ } else {
+ wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
+ wcid = rcu_dereference(dev->wcid[wcid_idx]);
+
+ if (wcid && wcid->sta) {
+ sta = container_of((void *)wcid, struct ieee80211_sta,
+ drv_priv);
+ spin_lock_bh(&dev->sta_poll_lock);
+ if (list_empty(&wcid->poll_list))
+ list_add_tail(&wcid->poll_list,
+ &dev->sta_poll_list);
+ spin_unlock_bh(&dev->sta_poll_lock);
+ }
+ }
+
+ if (sta && likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
+ mt76_connac2_tx_check_aggr(sta, txwi);
+
+ __mt76_tx_complete_skb(dev, wcid_idx, t->skb, free_list);
+out:
+ t->skb = NULL;
+ mt76_put_txwi(dev, t);
+}
+EXPORT_SYMBOL_GPL(mt76_connac2_txwi_free);
+
+void mt76_connac2_tx_token_put(struct mt76_dev *dev)
+{
+ struct mt76_txwi_cache *txwi;
+ int id;
+
+ spin_lock_bh(&dev->token_lock);
+ idr_for_each_entry(&dev->token, txwi, id) {
+ mt76_connac2_txwi_free(dev, txwi, NULL, NULL);
+ dev->token_count--;
+ }
+ spin_unlock_bh(&dev->token_lock);
+ idr_destroy(&dev->token);
+}
+EXPORT_SYMBOL_GPL(mt76_connac2_tx_token_put);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index 90c883c7fe05..1bb687bee8c8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -1158,7 +1158,7 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
static void mt7915_stop_hardware(struct mt7915_dev *dev)
{
mt7915_mcu_exit(dev);
- mt7915_tx_token_put(dev);
+ mt76_connac2_tx_token_put(&dev->mt76);
mt7915_dma_cleanup(dev);
tasklet_disable(&dev->mt76.irq_tasklet);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index 5c2c054b31fb..c8a09634c650 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -842,75 +842,6 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
return MT_TXD_SIZE + sizeof(*txp);
}
-static void
-mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
-{
- struct mt7915_sta *msta;
- u16 fc, tid;
- u32 val;
-
- if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
- return;
-
- tid = le32_get_bits(txwi[1], MT_TXD1_TID);
- if (tid >= 6) /* skip VO queue */
- return;
-
- val = le32_to_cpu(txwi[2]);
- fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
- FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
- if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
- return;
-
- msta = (struct mt7915_sta *)sta->drv_priv;
- if (!test_and_set_bit(tid, &msta->wcid.ampdu_state))
- ieee80211_start_tx_ba_session(sta, tid, 0);
-}
-
-static void
-mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
- struct ieee80211_sta *sta, struct list_head *free_list)
-{
- struct mt76_dev *mdev = &dev->mt76;
- struct mt7915_sta *msta;
- struct mt76_wcid *wcid;
- __le32 *txwi;
- u16 wcid_idx;
-
- mt76_connac_txp_skb_unmap(mdev, t);
- if (!t->skb)
- goto out;
-
- txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t);
- if (sta) {
- wcid = (struct mt76_wcid *)sta->drv_priv;
- wcid_idx = wcid->idx;
- } else {
- wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
- wcid = rcu_dereference(dev->mt76.wcid[wcid_idx]);
-
- if (wcid && wcid->sta) {
- msta = container_of(wcid, struct mt7915_sta, wcid);
- sta = container_of((void *)msta, struct ieee80211_sta,
- drv_priv);
- spin_lock_bh(&mdev->sta_poll_lock);
- if (list_empty(&msta->wcid.poll_list))
- list_add_tail(&msta->wcid.poll_list,
- &mdev->sta_poll_list);
- spin_unlock_bh(&mdev->sta_poll_lock);
- }
- }
-
- if (sta && likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
- mt7915_tx_check_aggr(sta, txwi);
-
- __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
-
-out:
- t->skb = NULL;
- mt76_put_txwi(mdev, t);
-}
-
static void
mt7915_mac_tx_free_prepare(struct mt7915_dev *dev)
{
@@ -1013,7 +944,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
if (!txwi)
continue;
- mt7915_txwi_free(dev, txwi, sta, &free_list);
+ mt76_connac2_txwi_free(mdev, txwi, sta, &free_list);
}
}
@@ -1045,7 +976,7 @@ mt7915_mac_tx_free_v0(struct mt7915_dev *dev, void *data, int len)
if (!txwi)
continue;
- mt7915_txwi_free(dev, txwi, NULL, &free_list);
+ mt76_connac2_txwi_free(mdev, txwi, NULL, &free_list);
}
mt7915_mac_tx_free_done(dev, &free_list, wake);
@@ -1360,20 +1291,6 @@ mt7915_update_beacons(struct mt7915_dev *dev)
mt7915_update_vif_beacon, mphy_ext->hw);
}
-void mt7915_tx_token_put(struct mt7915_dev *dev)
-{
- struct mt76_txwi_cache *txwi;
- int id;
-
- spin_lock_bh(&dev->mt76.token_lock);
- idr_for_each_entry(&dev->mt76.token, txwi, id) {
- mt7915_txwi_free(dev, txwi, NULL, NULL);
- dev->mt76.token_count--;
- }
- spin_unlock_bh(&dev->mt76.token_lock);
- idr_destroy(&dev->mt76.token);
-}
-
static int
mt7915_mac_restart(struct mt7915_dev *dev)
{
@@ -1418,7 +1335,7 @@ mt7915_mac_restart(struct mt7915_dev *dev)
napi_disable(&dev->mt76.tx_napi);
/* token reinit */
- mt7915_tx_token_put(dev);
+ mt76_connac2_tx_token_put(&dev->mt76);
idr_init(&dev->mt76.token);
mt7915_dma_reset(dev, true);
@@ -1607,7 +1524,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
mt7915_dma_reset(dev, false);
- mt7915_tx_token_put(dev);
+ mt76_connac2_tx_token_put(&dev->mt76);
idr_init(&dev->mt76.token);
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index ca01199afd11..ac116ab03690 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -608,7 +608,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info);
-void mt7915_tx_token_put(struct mt7915_dev *dev);
void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb, u32 *info);
bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index f0e67e62abc2..a62e4877f128 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -511,30 +511,6 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
return 0;
}
-static void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
-{
- struct mt7921_sta *msta;
- u16 fc, tid;
- u32 val;
-
- if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
- return;
-
- tid = le32_get_bits(txwi[1], MT_TXD1_TID);
- if (tid >= 6) /* skip VO queue */
- return;
-
- val = le32_to_cpu(txwi[2]);
- fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
- FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
- if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
- return;
-
- msta = (struct mt7921_sta *)sta->drv_priv;
- if (!test_and_set_bit(tid, &msta->wcid.ampdu_state))
- ieee80211_start_tx_ba_session(sta, tid, 0);
-}
-
void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
{
struct mt7921_sta *msta = NULL;
@@ -576,37 +552,6 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
rcu_read_unlock();
}
-void mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t,
- struct ieee80211_sta *sta, bool clear_status,
- struct list_head *free_list)
-{
- struct mt76_dev *mdev = &dev->mt76;
- __le32 *txwi;
- u16 wcid_idx;
-
- mt76_connac_txp_skb_unmap(mdev, t);
- if (!t->skb)
- goto out;
-
- txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t);
- if (sta) {
- struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
-
- if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
- mt7921_tx_check_aggr(sta, txwi);
-
- wcid_idx = wcid->idx;
- } else {
- wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
- }
-
- __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
-out:
- t->skb = NULL;
- mt76_put_txwi(mdev, t);
-}
-EXPORT_SYMBOL_GPL(mt7921_txwi_free);
-
static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
{
struct mt76_connac_tx_free *free = data;
@@ -630,7 +575,6 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
for (i = 0; i < count; i++) {
u32 msdu, info = le32_to_cpu(tx_info[i]);
- u8 stat;
/* 1'b1: new wcid pair.
* 1'b0: msdu_id with the same 'wcid pair' as above.
@@ -657,13 +601,11 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
}
msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info);
- stat = FIELD_GET(MT_TX_FREE_STATUS, info);
-
txwi = mt76_token_release(mdev, msdu, &wake);
if (!txwi)
continue;
- mt7921_txwi_free(dev, txwi, sta, stat, &free_list);
+ mt76_connac2_txwi_free(mdev, txwi, sta, &free_list);
}
if (wake)
@@ -1225,7 +1167,7 @@ void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
sta = wcid_to_sta(wcid);
if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE)))
- mt7921_tx_check_aggr(sta, txwi);
+ mt76_connac2_tx_check_aggr(sta, txwi);
skb_pull(e->skb, headroom);
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
index d4dfbbdb5f27..16188e2ae691 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
@@ -471,7 +471,6 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct mt76_tx_info *tx_info);
void mt7921_tx_worker(struct mt76_worker *w);
-void mt7921_tx_token_put(struct mt7921_dev *dev);
bool mt7921_rx_check(struct mt76_dev *mdev, void *data, int len);
void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb, u32 *info);
@@ -504,9 +503,6 @@ int mt7921_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void *data, int len);
int mt7921_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
struct netlink_callback *cb, void *data, int len);
-void mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t,
- struct ieee80211_sta *sta, bool clear_status,
- struct list_head *free_list);
int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
struct sk_buff *skb, int seq);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index 1c727870bbdb..6c06d4b5856e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -115,7 +115,7 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev)
cancel_work_sync(&pm->wake_work);
cancel_work_sync(&dev->reset_work);
- mt7921_tx_token_put(dev);
+ mt76_connac2_tx_token_put(&dev->mt76);
__mt7921_mcu_drv_pmctrl(dev);
mt7921_dma_cleanup(dev);
mt7921_wfsys_reset(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c
index 6053a2556c20..978c90a034cf 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c
@@ -53,20 +53,6 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
return 0;
}
-void mt7921_tx_token_put(struct mt7921_dev *dev)
-{
- struct mt76_txwi_cache *txwi;
- int id;
-
- spin_lock_bh(&dev->mt76.token_lock);
- idr_for_each_entry(&dev->mt76.token, txwi, id) {
- mt7921_txwi_free(dev, txwi, NULL, false, NULL);
- dev->mt76.token_count--;
- }
- spin_unlock_bh(&dev->mt76.token_lock);
- idr_destroy(&dev->mt76.token);
-}
-
int mt7921e_mac_reset(struct mt7921_dev *dev)
{
int i, err;
@@ -91,7 +77,7 @@ int mt7921e_mac_reset(struct mt7921_dev *dev)
napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]);
napi_disable(&dev->mt76.tx_napi);
- mt7921_tx_token_put(dev);
+ mt76_connac2_tx_token_put(&dev->mt76);
idr_init(&dev->mt76.token);
mt7921_wpdma_reset(dev, true);
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v2 13/15] wifi: mt76: move rate info in mt76_vif
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
` (11 preceding siblings ...)
2023-06-09 8:15 ` [PATCH v2 12/15] mt76: connac: move more mt7921/mt7915 mac shared code in connac lib Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 14/15] wifi: mt76: connac: move connac3 definitions in mt76_connac3_mac.h Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library Lorenzo Bianconi
14 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
This is a preliminary patch to introduce mt76_connac3 mac library used
by WiFi7 chipsets (e.g. mt7996).
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt76.h | 3 +++
drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 10 +++++-----
drivers/net/wireless/mediatek/mt76/mt7996/main.c | 10 +++++-----
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 4 ----
5 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 878cebb8a4e9..d14844d7c5bb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -705,6 +705,9 @@ struct mt76_vif {
u8 wmm_idx;
u8 scan_seq_num;
u8 cipher;
+ u8 basic_rates_idx;
+ u8 mcast_rates_idx;
+ u8 beacon_rates_idx;
};
struct mt76_phy {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 753e9c7b1199..e407fc547e42 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -1008,7 +1008,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
- struct mt7996_vif *mvif;
+ struct mt76_vif *mvif;
u16 tx_count = 15;
u32 val;
bool beacon = !!(changed & (BSS_CHANGED_BEACON |
@@ -1016,11 +1016,11 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
BSS_CHANGED_FILS_DISCOVERY));
- mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL;
+ mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL;
if (mvif) {
- omac_idx = mvif->mt76.omac_idx;
- wmm_idx = mvif->mt76.wmm_idx;
- band_idx = mvif->mt76.band_idx;
+ omac_idx = mvif->omac_idx;
+ wmm_idx = mvif->wmm_idx;
+ band_idx = mvif->band_idx;
}
if (inband_disc) {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 2d20de7c8916..ee9e409b8eb9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -221,9 +221,9 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ)
- mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL + 4;
+ mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL + 4;
else
- mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL;
+ mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL;
mt7996_init_bitrate_mask(vif);
@@ -506,7 +506,7 @@ static u8
mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
bool beacon, bool mcast)
{
- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct mt76_phy *mphy = hw->priv;
u16 rate;
u8 i, idx, ht;
@@ -518,7 +518,7 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct mt7996_dev *dev = mt7996_hw_dev(hw);
/* must odd index */
- idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->mt76.idx % 20);
+ idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->idx % 20);
mt7996_mac_set_fixed_rate_table(dev, idx, rate);
return idx;
}
@@ -536,7 +536,7 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *info,
u64 changed)
{
- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct mt7996_phy *phy = mt7996_hw_phy(hw);
struct mt7996_dev *dev = mt7996_hw_dev(hw);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 88e2f9d0e513..6cc87835263a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -600,7 +600,7 @@ static void
mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
struct mt7996_phy *phy)
{
- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct bss_rate_tlv *bmc;
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
enum nl80211_band band = chandef->chan->band;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 829973abc28d..c8e8a04a561e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -120,10 +120,6 @@ struct mt7996_vif {
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
struct cfg80211_bitrate_mask bitrate_mask;
-
- u8 basic_rates_idx;
- u8 mcast_rates_idx;
- u8 beacon_rates_idx;
};
/* per-phy stats. */
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v2 14/15] wifi: mt76: connac: move connac3 definitions in mt76_connac3_mac.h
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
` (12 preceding siblings ...)
2023-06-09 8:15 ` [PATCH v2 13/15] wifi: mt76: move rate info in mt76_vif Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 8:15 ` [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library Lorenzo Bianconi
14 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
Connac3 mac definitions are shared between WiFi7 chipsets so move them in
mt76_connac3_mac.h
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
.../wireless/mediatek/mt76/mt76_connac3_mac.h | 325 ++++++++++++++++++
.../net/wireless/mediatek/mt76/mt7996/mac.h | 315 +----------------
2 files changed, 326 insertions(+), 314 deletions(-)
create mode 100644 drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
new file mode 100644
index 000000000000..6663a0b46541
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
@@ -0,0 +1,325 @@
+/* SPDX-License-Identifier: ISC */
+/* Copyright (C) 2023 MediaTek Inc. */
+
+#ifndef __MT76_CONNAC3_MAC_H
+#define __MT76_CONNAC3_MAC_H
+
+#define MT_CT_PARSE_LEN 72
+#define MT_CT_DMA_BUF_NUM 2
+
+#define MT_RXD0_LENGTH GENMASK(15, 0)
+#define MT_RXD0_PKT_FLAG GENMASK(19, 16)
+#define MT_RXD0_PKT_TYPE GENMASK(31, 27)
+
+#define MT_RXD0_MESH BIT(18)
+#define MT_RXD0_MHCP BIT(19)
+#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
+#define MT_RXD0_NORMAL_IP_SUM BIT(23)
+#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
+
+#define MT_RXD0_SW_PKT_TYPE_MASK GENMASK(31, 16)
+#define MT_RXD0_SW_PKT_TYPE_MAP 0x380F
+#define MT_RXD0_SW_PKT_TYPE_FRAME 0x3801
+
+/* RXD DW1 */
+#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(11, 0)
+#define MT_RXD1_NORMAL_GROUP_1 BIT(16)
+#define MT_RXD1_NORMAL_GROUP_2 BIT(17)
+#define MT_RXD1_NORMAL_GROUP_3 BIT(18)
+#define MT_RXD1_NORMAL_GROUP_4 BIT(19)
+#define MT_RXD1_NORMAL_GROUP_5 BIT(20)
+#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21)
+#define MT_RXD1_NORMAL_CM BIT(23)
+#define MT_RXD1_NORMAL_CLM BIT(24)
+#define MT_RXD1_NORMAL_ICV_ERR BIT(25)
+#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26)
+#define MT_RXD1_NORMAL_BAND_IDX GENMASK(28, 27)
+#define MT_RXD1_NORMAL_SPP_EN BIT(29)
+#define MT_RXD1_NORMAL_ADD_OM BIT(30)
+#define MT_RXD1_NORMAL_SEC_DONE BIT(31)
+
+/* RXD DW2 */
+#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0)
+#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8)
+#define MT_RXD2_NORMAL_HDR_TRANS BIT(7)
+#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 13)
+#define MT_RXD2_NORMAL_SEC_MODE GENMASK(20, 16)
+#define MT_RXD2_NORMAL_MU_BAR BIT(21)
+#define MT_RXD2_NORMAL_SW_BIT BIT(22)
+#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23)
+#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24)
+#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25)
+#define MT_RXD2_NORMAL_INT_FRAME BIT(26)
+#define MT_RXD2_NORMAL_FRAG BIT(27)
+#define MT_RXD2_NORMAL_NULL_FRAME BIT(28)
+#define MT_RXD2_NORMAL_NDATA BIT(29)
+#define MT_RXD2_NORMAL_NON_AMPDU BIT(30)
+#define MT_RXD2_NORMAL_BF_REPORT BIT(31)
+
+/* RXD DW3 */
+#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
+#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8)
+#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16)
+#define MT_RXD3_NORMAL_U2M BIT(0)
+#define MT_RXD3_NORMAL_HTC_VLD BIT(18)
+#define MT_RXD3_NORMAL_BEACON_MC BIT(20)
+#define MT_RXD3_NORMAL_BEACON_UC BIT(21)
+#define MT_RXD3_NORMAL_CO_ANT BIT(22)
+#define MT_RXD3_NORMAL_FCS_ERR BIT(24)
+#define MT_RXD3_NORMAL_VLAN2ETH BIT(31)
+
+/* RXD DW4 */
+#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0)
+#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0)
+#define MT_RXD4_MID_AMSDU_FRAME BIT(1)
+#define MT_RXD4_LAST_AMSDU_FRAME BIT(0)
+
+#define MT_RXV_HDR_BAND_IDX BIT(24)
+
+/* RXD GROUP4 */
+#define MT_RXD8_FRAME_CONTROL GENMASK(15, 0)
+
+#define MT_RXD10_SEQ_CTRL GENMASK(15, 0)
+#define MT_RXD10_QOS_CTL GENMASK(31, 16)
+
+#define MT_RXD11_HT_CONTROL GENMASK(31, 0)
+
+/* P-RXV */
+#define MT_PRXV_TX_RATE GENMASK(6, 0)
+#define MT_PRXV_TX_DCM BIT(4)
+#define MT_PRXV_TX_ER_SU_106T BIT(5)
+#define MT_PRXV_NSTS GENMASK(10, 7)
+#define MT_PRXV_TXBF BIT(11)
+#define MT_PRXV_HT_AD_CODE BIT(12)
+#define MT_PRXV_HE_RU_ALLOC GENMASK(30, 22)
+#define MT_PRXV_RCPI3 GENMASK(31, 24)
+#define MT_PRXV_RCPI2 GENMASK(23, 16)
+#define MT_PRXV_RCPI1 GENMASK(15, 8)
+#define MT_PRXV_RCPI0 GENMASK(7, 0)
+#define MT_PRXV_HT_SHORT_GI GENMASK(4, 3)
+#define MT_PRXV_HT_STBC GENMASK(10, 9)
+#define MT_PRXV_TX_MODE GENMASK(14, 11)
+#define MT_PRXV_FRAME_MODE GENMASK(2, 0)
+#define MT_PRXV_DCM BIT(5)
+
+/* C-RXV */
+#define MT_CRXV_HE_NUM_USER GENMASK(26, 20)
+#define MT_CRXV_HE_LTF_SIZE GENMASK(28, 27)
+#define MT_CRXV_HE_LDPC_EXT_SYM BIT(30)
+
+#define MT_CRXV_HE_PE_DISAMBIG BIT(1)
+#define MT_CRXV_HE_UPLINK BIT(2)
+
+#define MT_CRXV_HE_MU_AID GENMASK(27, 17)
+#define MT_CRXV_HE_BEAM_CHNG BIT(29)
+
+#define MT_CRXV_HE_DOPPLER BIT(0)
+#define MT_CRXV_HE_BSS_COLOR GENMASK(15, 10)
+#define MT_CRXV_HE_TXOP_DUR GENMASK(19, 17)
+
+#define MT_CRXV_HE_SR_MASK GENMASK(11, 8)
+#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
+#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
+#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21)
+
+#define MT_CRXV_HE_RU0 GENMASK(8, 0)
+#define MT_CRXV_HE_RU1 GENMASK(17, 9)
+#define MT_CRXV_HE_RU2 GENMASK(26, 18)
+#define MT_CRXV_HE_RU3_L GENMASK(31, 27)
+#define MT_CRXV_HE_RU3_H GENMASK(3, 0)
+
+enum tx_header_format {
+ MT_HDR_FORMAT_802_3,
+ MT_HDR_FORMAT_CMD,
+ MT_HDR_FORMAT_802_11,
+ MT_HDR_FORMAT_802_11_EXT,
+};
+
+enum tx_pkt_type {
+ MT_TX_TYPE_CT,
+ MT_TX_TYPE_SF,
+ MT_TX_TYPE_CMD,
+ MT_TX_TYPE_FW,
+};
+
+enum tx_port_idx {
+ MT_TX_PORT_IDX_LMAC,
+ MT_TX_PORT_IDX_MCU
+};
+
+enum tx_mcu_port_q_idx {
+ MT_TX_MCU_PORT_RX_Q0 = 0x20,
+ MT_TX_MCU_PORT_RX_Q1,
+ MT_TX_MCU_PORT_RX_Q2,
+ MT_TX_MCU_PORT_RX_Q3,
+ MT_TX_MCU_PORT_RX_FWDL = 0x3e
+};
+
+enum tx_mgnt_type {
+ MT_TX_NORMAL,
+ MT_TX_TIMING,
+ MT_TX_ADDBA,
+};
+
+#define MT_CT_INFO_APPLY_TXD BIT(0)
+#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1)
+#define MT_CT_INFO_MGMT_FRAME BIT(2)
+#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3)
+#define MT_CT_INFO_HSR2_TX BIT(4)
+#define MT_CT_INFO_FROM_HOST BIT(7)
+
+#define MT_TXD_SIZE (8 * 4)
+
+#define MT_TXD0_Q_IDX GENMASK(31, 25)
+#define MT_TXD0_PKT_FMT GENMASK(24, 23)
+#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
+#define MT_TXD0_TX_BYTES GENMASK(15, 0)
+
+#define MT_TXD1_FIXED_RATE BIT(31)
+#define MT_TXD1_OWN_MAC GENMASK(30, 25)
+#define MT_TXD1_TID GENMASK(24, 21)
+#define MT_TXD1_BIP BIT(24)
+#define MT_TXD1_ETH_802_3 BIT(20)
+#define MT_TXD1_HDR_INFO GENMASK(20, 16)
+#define MT_TXD1_HDR_FORMAT GENMASK(15, 14)
+#define MT_TXD1_TGID GENMASK(13, 12)
+#define MT_TXD1_WLAN_IDX GENMASK(11, 0)
+
+#define MT_TXD2_POWER_OFFSET GENMASK(31, 26)
+#define MT_TXD2_MAX_TX_TIME GENMASK(25, 16)
+#define MT_TXD2_FRAG GENMASK(15, 14)
+#define MT_TXD2_HTC_VLD BIT(13)
+#define MT_TXD2_DURATION BIT(12)
+#define MT_TXD2_HDR_PAD GENMASK(11, 10)
+#define MT_TXD2_RTS BIT(9)
+#define MT_TXD2_OWN_MAC_MAP BIT(8)
+#define MT_TXD2_BF_TYPE GENMASK(6, 7)
+#define MT_TXD2_FRAME_TYPE GENMASK(5, 4)
+#define MT_TXD2_SUB_TYPE GENMASK(3, 0)
+
+#define MT_TXD3_SN_VALID BIT(31)
+#define MT_TXD3_PN_VALID BIT(30)
+#define MT_TXD3_SW_POWER_MGMT BIT(29)
+#define MT_TXD3_BA_DISABLE BIT(28)
+#define MT_TXD3_SEQ GENMASK(27, 16)
+#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11)
+#define MT_TXD3_TX_COUNT GENMASK(10, 6)
+#define MT_TXD3_HW_AMSDU BIT(5)
+#define MT_TXD3_BCM BIT(4)
+#define MT_TXD3_EEOSP BIT(3)
+#define MT_TXD3_EMRD BIT(2)
+#define MT_TXD3_PROTECT_FRAME BIT(1)
+#define MT_TXD3_NO_ACK BIT(0)
+
+#define MT_TXD4_PN_LOW GENMASK(31, 0)
+
+#define MT_TXD5_PN_HIGH GENMASK(31, 16)
+#define MT_TXD5_FL BIT(15)
+#define MT_TXD5_BYPASS_TBB BIT(14)
+#define MT_TXD5_BYPASS_RBB BIT(13)
+#define MT_TXD5_BSS_COLOR_ZERO BIT(12)
+#define MT_TXD5_TX_STATUS_HOST BIT(10)
+#define MT_TXD5_TX_STATUS_MCU BIT(9)
+#define MT_TXD5_TX_STATUS_FMT BIT(8)
+#define MT_TXD5_PID GENMASK(7, 0)
+
+#define MT_TXD6_TX_SRC GENMASK(31, 30)
+#define MT_TXD6_VTA BIT(28)
+#define MT_TXD6_BW GENMASK(25, 22)
+#define MT_TXD6_TX_RATE GENMASK(21, 16)
+#define MT_TXD6_TIMESTAMP_OFS_EN BIT(15)
+#define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10)
+#define MT_TXD6_MSDU_CNT GENMASK(9, 4)
+#define MT_TXD6_DIS_MAT BIT(3)
+#define MT_TXD6_DAS BIT(2)
+#define MT_TXD6_AMSDU_CAP BIT(1)
+
+#define MT_TXD7_TXD_LEN GENMASK(31, 30)
+#define MT_TXD7_IP_SUM BIT(29)
+#define MT_TXD7_DROP_BY_SDO BIT(28)
+#define MT_TXD7_MAC_TXD BIT(27)
+#define MT_TXD7_CTXD BIT(26)
+#define MT_TXD7_CTXD_CNT GENMASK(25, 22)
+#define MT_TXD7_UDP_TCP_SUM BIT(15)
+#define MT_TXD7_TX_TIME GENMASK(9, 0)
+
+#define MT_TX_RATE_STBC BIT(14)
+#define MT_TX_RATE_NSS GENMASK(13, 10)
+#define MT_TX_RATE_MODE GENMASK(9, 6)
+#define MT_TX_RATE_SU_EXT_TONE BIT(5)
+#define MT_TX_RATE_DCM BIT(4)
+/* VHT/HE only use bits 0-3 */
+#define MT_TX_RATE_IDX GENMASK(5, 0)
+
+#define MT_TXFREE0_PKT_TYPE GENMASK(31, 27)
+#define MT_TXFREE0_MSDU_CNT GENMASK(25, 16)
+#define MT_TXFREE0_RX_BYTE GENMASK(15, 0)
+
+#define MT_TXFREE1_VER GENMASK(18, 16)
+
+#define MT_TXFREE_INFO_PAIR BIT(31)
+#define MT_TXFREE_INFO_HEADER BIT(30)
+#define MT_TXFREE_INFO_WLAN_ID GENMASK(23, 12)
+#define MT_TXFREE_INFO_MSDU_ID GENMASK(14, 0)
+#define MT_TXFREE_INFO_COUNT GENMASK(27, 24)
+#define MT_TXFREE_INFO_STAT GENMASK(29, 28)
+
+#define MT_TXS0_BW GENMASK(31, 29)
+#define MT_TXS0_TID GENMASK(28, 26)
+#define MT_TXS0_AMPDU BIT(25)
+#define MT_TXS0_TXS_FORMAT GENMASK(24, 23)
+#define MT_TXS0_BA_ERROR BIT(22)
+#define MT_TXS0_PS_FLAG BIT(21)
+#define MT_TXS0_TXOP_TIMEOUT BIT(20)
+#define MT_TXS0_BIP_ERROR BIT(19)
+
+#define MT_TXS0_QUEUE_TIMEOUT BIT(18)
+#define MT_TXS0_RTS_TIMEOUT BIT(17)
+#define MT_TXS0_ACK_TIMEOUT BIT(16)
+#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16)
+
+#define MT_TXS0_TX_STATUS_HOST BIT(15)
+#define MT_TXS0_TX_STATUS_MCU BIT(14)
+#define MT_TXS0_TX_RATE GENMASK(13, 0)
+
+#define MT_TXS1_SEQNO GENMASK(31, 20)
+#define MT_TXS1_RESP_RATE GENMASK(19, 16)
+#define MT_TXS1_RXV_SEQNO GENMASK(15, 8)
+#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0)
+
+#define MT_TXS2_BF_STATUS GENMASK(31, 30)
+#define MT_TXS2_BAND GENMASK(29, 28)
+#define MT_TXS2_WCID GENMASK(27, 16)
+#define MT_TXS2_TX_DELAY GENMASK(15, 0)
+
+#define MT_TXS3_PID GENMASK(31, 24)
+#define MT_TXS3_RATE_STBC BIT(7)
+#define MT_TXS3_FIXED_RATE BIT(6)
+#define MT_TXS3_SRC GENMASK(5, 4)
+#define MT_TXS3_SHARED_ANTENNA BIT(3)
+#define MT_TXS3_LAST_TX_RATE GENMASK(2, 0)
+
+#define MT_TXS4_TIMESTAMP GENMASK(31, 0)
+
+#define MT_TXS5_F0_FINAL_MPDU BIT(31)
+#define MT_TXS5_F0_QOS BIT(30)
+#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25)
+#define MT_TXS5_F0_FRONT_TIME GENMASK(24, 0)
+#define MT_TXS5_F1_MPDU_TX_COUNT GENMASK(31, 24)
+#define MT_TXS5_F1_MPDU_TX_BYTES GENMASK(23, 0)
+
+#define MT_TXS6_F0_NOISE_3 GENMASK(31, 24)
+#define MT_TXS6_F0_NOISE_2 GENMASK(23, 16)
+#define MT_TXS6_F0_NOISE_1 GENMASK(15, 8)
+#define MT_TXS6_F0_NOISE_0 GENMASK(7, 0)
+#define MT_TXS6_F1_MPDU_FAIL_COUNT GENMASK(31, 24)
+#define MT_TXS6_F1_MPDU_FAIL_BYTES GENMASK(23, 0)
+
+#define MT_TXS7_F0_RCPI_3 GENMASK(31, 24)
+#define MT_TXS7_F0_RCPI_2 GENMASK(23, 16)
+#define MT_TXS7_F0_RCPI_1 GENMASK(15, 8)
+#define MT_TXS7_F0_RCPI_0 GENMASK(7, 0)
+#define MT_TXS7_F1_MPDU_RETRY_COUNT GENMASK(31, 24)
+#define MT_TXS7_F1_MPDU_RETRY_BYTES GENMASK(23, 0)
+
+#endif /* __MT76_CONNAC3_MAC_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h
index bc4e6c55373e..e629324a5617 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h
@@ -6,320 +6,7 @@
#ifndef __MT7996_MAC_H
#define __MT7996_MAC_H
-#define MT_CT_PARSE_LEN 72
-#define MT_CT_DMA_BUF_NUM 2
-
-#define MT_RXD0_LENGTH GENMASK(15, 0)
-#define MT_RXD0_PKT_TYPE GENMASK(31, 27)
-
-#define MT_RXD0_MESH BIT(18)
-#define MT_RXD0_MHCP BIT(19)
-#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
-#define MT_RXD0_NORMAL_IP_SUM BIT(23)
-#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
-
-#define MT_RXD0_SW_PKT_TYPE_MASK GENMASK(31, 16)
-#define MT_RXD0_SW_PKT_TYPE_MAP 0x380F
-#define MT_RXD0_SW_PKT_TYPE_FRAME 0x3801
-
-/* RXD DW1 */
-#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(11, 0)
-#define MT_RXD1_NORMAL_GROUP_1 BIT(16)
-#define MT_RXD1_NORMAL_GROUP_2 BIT(17)
-#define MT_RXD1_NORMAL_GROUP_3 BIT(18)
-#define MT_RXD1_NORMAL_GROUP_4 BIT(19)
-#define MT_RXD1_NORMAL_GROUP_5 BIT(20)
-#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21)
-#define MT_RXD1_NORMAL_CM BIT(23)
-#define MT_RXD1_NORMAL_CLM BIT(24)
-#define MT_RXD1_NORMAL_ICV_ERR BIT(25)
-#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26)
-#define MT_RXD1_NORMAL_BAND_IDX GENMASK(28, 27)
-#define MT_RXD1_NORMAL_SPP_EN BIT(29)
-#define MT_RXD1_NORMAL_ADD_OM BIT(30)
-#define MT_RXD1_NORMAL_SEC_DONE BIT(31)
-
-/* RXD DW2 */
-#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0)
-#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8)
-#define MT_RXD2_NORMAL_HDR_TRANS BIT(7)
-#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 13)
-#define MT_RXD2_NORMAL_SEC_MODE GENMASK(20, 16)
-#define MT_RXD2_NORMAL_MU_BAR BIT(21)
-#define MT_RXD2_NORMAL_SW_BIT BIT(22)
-#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23)
-#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24)
-#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25)
-#define MT_RXD2_NORMAL_INT_FRAME BIT(26)
-#define MT_RXD2_NORMAL_FRAG BIT(27)
-#define MT_RXD2_NORMAL_NULL_FRAME BIT(28)
-#define MT_RXD2_NORMAL_NDATA BIT(29)
-#define MT_RXD2_NORMAL_NON_AMPDU BIT(30)
-#define MT_RXD2_NORMAL_BF_REPORT BIT(31)
-
-/* RXD DW3 */
-#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
-#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8)
-#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16)
-#define MT_RXD3_NORMAL_U2M BIT(0)
-#define MT_RXD3_NORMAL_HTC_VLD BIT(18)
-#define MT_RXD3_NORMAL_BEACON_MC BIT(20)
-#define MT_RXD3_NORMAL_BEACON_UC BIT(21)
-#define MT_RXD3_NORMAL_CO_ANT BIT(22)
-#define MT_RXD3_NORMAL_FCS_ERR BIT(24)
-#define MT_RXD3_NORMAL_VLAN2ETH BIT(31)
-
-/* RXD DW4 */
-#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0)
-#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0)
-#define MT_RXD4_MID_AMSDU_FRAME BIT(1)
-#define MT_RXD4_LAST_AMSDU_FRAME BIT(0)
-
-#define MT_RXV_HDR_BAND_IDX BIT(24)
-
-/* RXD GROUP4 */
-#define MT_RXD8_FRAME_CONTROL GENMASK(15, 0)
-
-#define MT_RXD10_SEQ_CTRL GENMASK(15, 0)
-#define MT_RXD10_QOS_CTL GENMASK(31, 16)
-
-#define MT_RXD11_HT_CONTROL GENMASK(31, 0)
-
-/* P-RXV */
-#define MT_PRXV_TX_RATE GENMASK(6, 0)
-#define MT_PRXV_TX_DCM BIT(4)
-#define MT_PRXV_TX_ER_SU_106T BIT(5)
-#define MT_PRXV_NSTS GENMASK(10, 7)
-#define MT_PRXV_TXBF BIT(11)
-#define MT_PRXV_HT_AD_CODE BIT(12)
-#define MT_PRXV_HE_RU_ALLOC GENMASK(30, 22)
-#define MT_PRXV_RCPI3 GENMASK(31, 24)
-#define MT_PRXV_RCPI2 GENMASK(23, 16)
-#define MT_PRXV_RCPI1 GENMASK(15, 8)
-#define MT_PRXV_RCPI0 GENMASK(7, 0)
-#define MT_PRXV_HT_SHORT_GI GENMASK(4, 3)
-#define MT_PRXV_HT_STBC GENMASK(10, 9)
-#define MT_PRXV_TX_MODE GENMASK(14, 11)
-#define MT_PRXV_FRAME_MODE GENMASK(2, 0)
-#define MT_PRXV_DCM BIT(5)
-
-/* C-RXV */
-#define MT_CRXV_HE_NUM_USER GENMASK(26, 20)
-#define MT_CRXV_HE_LTF_SIZE GENMASK(28, 27)
-#define MT_CRXV_HE_LDPC_EXT_SYM BIT(30)
-
-#define MT_CRXV_HE_PE_DISAMBIG BIT(1)
-#define MT_CRXV_HE_UPLINK BIT(2)
-
-#define MT_CRXV_HE_MU_AID GENMASK(27, 17)
-#define MT_CRXV_HE_BEAM_CHNG BIT(29)
-
-#define MT_CRXV_HE_DOPPLER BIT(0)
-#define MT_CRXV_HE_BSS_COLOR GENMASK(15, 10)
-#define MT_CRXV_HE_TXOP_DUR GENMASK(19, 17)
-
-#define MT_CRXV_HE_SR_MASK GENMASK(11, 8)
-#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
-#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
-#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21)
-
-#define MT_CRXV_HE_RU0 GENMASK(8, 0)
-#define MT_CRXV_HE_RU1 GENMASK(17, 9)
-#define MT_CRXV_HE_RU2 GENMASK(26, 18)
-#define MT_CRXV_HE_RU3_L GENMASK(31, 27)
-#define MT_CRXV_HE_RU3_H GENMASK(3, 0)
-
-enum tx_header_format {
- MT_HDR_FORMAT_802_3,
- MT_HDR_FORMAT_CMD,
- MT_HDR_FORMAT_802_11,
- MT_HDR_FORMAT_802_11_EXT,
-};
-
-enum tx_pkt_type {
- MT_TX_TYPE_CT,
- MT_TX_TYPE_SF,
- MT_TX_TYPE_CMD,
- MT_TX_TYPE_FW,
-};
-
-enum tx_port_idx {
- MT_TX_PORT_IDX_LMAC,
- MT_TX_PORT_IDX_MCU
-};
-
-enum tx_mcu_port_q_idx {
- MT_TX_MCU_PORT_RX_Q0 = 0x20,
- MT_TX_MCU_PORT_RX_Q1,
- MT_TX_MCU_PORT_RX_Q2,
- MT_TX_MCU_PORT_RX_Q3,
- MT_TX_MCU_PORT_RX_FWDL = 0x3e
-};
-
-enum tx_mgnt_type {
- MT_TX_NORMAL,
- MT_TX_TIMING,
- MT_TX_ADDBA,
-};
-
-#define MT_CT_INFO_APPLY_TXD BIT(0)
-#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1)
-#define MT_CT_INFO_MGMT_FRAME BIT(2)
-#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3)
-#define MT_CT_INFO_HSR2_TX BIT(4)
-#define MT_CT_INFO_FROM_HOST BIT(7)
-
-#define MT_TXD_SIZE (8 * 4)
-
-#define MT_TXD0_Q_IDX GENMASK(31, 25)
-#define MT_TXD0_PKT_FMT GENMASK(24, 23)
-#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
-#define MT_TXD0_TX_BYTES GENMASK(15, 0)
-
-#define MT_TXD1_FIXED_RATE BIT(31)
-#define MT_TXD1_OWN_MAC GENMASK(30, 25)
-#define MT_TXD1_TID GENMASK(24, 21)
-#define MT_TXD1_BIP BIT(24)
-#define MT_TXD1_ETH_802_3 BIT(20)
-#define MT_TXD1_HDR_INFO GENMASK(20, 16)
-#define MT_TXD1_HDR_FORMAT GENMASK(15, 14)
-#define MT_TXD1_TGID GENMASK(13, 12)
-#define MT_TXD1_WLAN_IDX GENMASK(11, 0)
-
-#define MT_TXD2_POWER_OFFSET GENMASK(31, 26)
-#define MT_TXD2_MAX_TX_TIME GENMASK(25, 16)
-#define MT_TXD2_FRAG GENMASK(15, 14)
-#define MT_TXD2_HTC_VLD BIT(13)
-#define MT_TXD2_DURATION BIT(12)
-#define MT_TXD2_HDR_PAD GENMASK(11, 10)
-#define MT_TXD2_RTS BIT(9)
-#define MT_TXD2_OWN_MAC_MAP BIT(8)
-#define MT_TXD2_BF_TYPE GENMASK(6, 7)
-#define MT_TXD2_FRAME_TYPE GENMASK(5, 4)
-#define MT_TXD2_SUB_TYPE GENMASK(3, 0)
-
-#define MT_TXD3_SN_VALID BIT(31)
-#define MT_TXD3_PN_VALID BIT(30)
-#define MT_TXD3_SW_POWER_MGMT BIT(29)
-#define MT_TXD3_BA_DISABLE BIT(28)
-#define MT_TXD3_SEQ GENMASK(27, 16)
-#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11)
-#define MT_TXD3_TX_COUNT GENMASK(10, 6)
-#define MT_TXD3_HW_AMSDU BIT(5)
-#define MT_TXD3_BCM BIT(4)
-#define MT_TXD3_EEOSP BIT(3)
-#define MT_TXD3_EMRD BIT(2)
-#define MT_TXD3_PROTECT_FRAME BIT(1)
-#define MT_TXD3_NO_ACK BIT(0)
-
-#define MT_TXD4_PN_LOW GENMASK(31, 0)
-
-#define MT_TXD5_PN_HIGH GENMASK(31, 16)
-#define MT_TXD5_FL BIT(15)
-#define MT_TXD5_BYPASS_TBB BIT(14)
-#define MT_TXD5_BYPASS_RBB BIT(13)
-#define MT_TXD5_BSS_COLOR_ZERO BIT(12)
-#define MT_TXD5_TX_STATUS_HOST BIT(10)
-#define MT_TXD5_TX_STATUS_MCU BIT(9)
-#define MT_TXD5_TX_STATUS_FMT BIT(8)
-#define MT_TXD5_PID GENMASK(7, 0)
-
-#define MT_TXD6_TX_SRC GENMASK(31, 30)
-#define MT_TXD6_VTA BIT(28)
-#define MT_TXD6_BW GENMASK(25, 22)
-#define MT_TXD6_TX_RATE GENMASK(21, 16)
-#define MT_TXD6_TIMESTAMP_OFS_EN BIT(15)
-#define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10)
-#define MT_TXD6_MSDU_CNT GENMASK(9, 4)
-#define MT_TXD6_DIS_MAT BIT(3)
-#define MT_TXD6_DAS BIT(2)
-#define MT_TXD6_AMSDU_CAP BIT(1)
-
-#define MT_TXD7_TXD_LEN GENMASK(31, 30)
-#define MT_TXD7_IP_SUM BIT(29)
-#define MT_TXD7_DROP_BY_SDO BIT(28)
-#define MT_TXD7_MAC_TXD BIT(27)
-#define MT_TXD7_CTXD BIT(26)
-#define MT_TXD7_CTXD_CNT GENMASK(25, 22)
-#define MT_TXD7_UDP_TCP_SUM BIT(15)
-#define MT_TXD7_TX_TIME GENMASK(9, 0)
-
-#define MT_TX_RATE_STBC BIT(14)
-#define MT_TX_RATE_NSS GENMASK(13, 10)
-#define MT_TX_RATE_MODE GENMASK(9, 6)
-#define MT_TX_RATE_SU_EXT_TONE BIT(5)
-#define MT_TX_RATE_DCM BIT(4)
-/* VHT/HE only use bits 0-3 */
-#define MT_TX_RATE_IDX GENMASK(5, 0)
-
-#define MT_TXFREE0_PKT_TYPE GENMASK(31, 27)
-#define MT_TXFREE0_MSDU_CNT GENMASK(25, 16)
-#define MT_TXFREE0_RX_BYTE GENMASK(15, 0)
-
-#define MT_TXFREE1_VER GENMASK(18, 16)
-
-#define MT_TXFREE_INFO_PAIR BIT(31)
-#define MT_TXFREE_INFO_HEADER BIT(30)
-#define MT_TXFREE_INFO_WLAN_ID GENMASK(23, 12)
-#define MT_TXFREE_INFO_MSDU_ID GENMASK(14, 0)
-
-#define MT_TXS0_BW GENMASK(31, 29)
-#define MT_TXS0_TID GENMASK(28, 26)
-#define MT_TXS0_AMPDU BIT(25)
-#define MT_TXS0_TXS_FORMAT GENMASK(24, 23)
-#define MT_TXS0_BA_ERROR BIT(22)
-#define MT_TXS0_PS_FLAG BIT(21)
-#define MT_TXS0_TXOP_TIMEOUT BIT(20)
-#define MT_TXS0_BIP_ERROR BIT(19)
-
-#define MT_TXS0_QUEUE_TIMEOUT BIT(18)
-#define MT_TXS0_RTS_TIMEOUT BIT(17)
-#define MT_TXS0_ACK_TIMEOUT BIT(16)
-#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16)
-
-#define MT_TXS0_TX_STATUS_HOST BIT(15)
-#define MT_TXS0_TX_STATUS_MCU BIT(14)
-#define MT_TXS0_TX_RATE GENMASK(13, 0)
-
-#define MT_TXS1_SEQNO GENMASK(31, 20)
-#define MT_TXS1_RESP_RATE GENMASK(19, 16)
-#define MT_TXS1_RXV_SEQNO GENMASK(15, 8)
-#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0)
-
-#define MT_TXS2_BF_STATUS GENMASK(31, 30)
-#define MT_TXS2_BAND GENMASK(29, 28)
-#define MT_TXS2_WCID GENMASK(27, 16)
-#define MT_TXS2_TX_DELAY GENMASK(15, 0)
-
-#define MT_TXS3_PID GENMASK(31, 24)
-#define MT_TXS3_RATE_STBC BIT(7)
-#define MT_TXS3_FIXED_RATE BIT(6)
-#define MT_TXS3_SRC GENMASK(5, 4)
-#define MT_TXS3_SHARED_ANTENNA BIT(3)
-#define MT_TXS3_LAST_TX_RATE GENMASK(2, 0)
-
-#define MT_TXS4_TIMESTAMP GENMASK(31, 0)
-
-#define MT_TXS5_F0_FINAL_MPDU BIT(31)
-#define MT_TXS5_F0_QOS BIT(30)
-#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25)
-#define MT_TXS5_F0_FRONT_TIME GENMASK(24, 0)
-#define MT_TXS5_F1_MPDU_TX_COUNT GENMASK(31, 24)
-#define MT_TXS5_F1_MPDU_TX_BYTES GENMASK(23, 0)
-
-#define MT_TXS6_F0_NOISE_3 GENMASK(31, 24)
-#define MT_TXS6_F0_NOISE_2 GENMASK(23, 16)
-#define MT_TXS6_F0_NOISE_1 GENMASK(15, 8)
-#define MT_TXS6_F0_NOISE_0 GENMASK(7, 0)
-#define MT_TXS6_F1_MPDU_FAIL_COUNT GENMASK(31, 24)
-#define MT_TXS6_F1_MPDU_FAIL_BYTES GENMASK(23, 0)
-
-#define MT_TXS7_F0_RCPI_3 GENMASK(31, 24)
-#define MT_TXS7_F0_RCPI_2 GENMASK(23, 16)
-#define MT_TXS7_F0_RCPI_1 GENMASK(15, 8)
-#define MT_TXS7_F0_RCPI_0 GENMASK(7, 0)
-#define MT_TXS7_F1_MPDU_RETRY_COUNT GENMASK(31, 24)
-#define MT_TXS7_F1_MPDU_RETRY_BYTES GENMASK(23, 0)
+#include "../mt76_connac3_mac.h"
struct mt7996_dfs_pulse {
u32 max_width; /* us */
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library
2023-06-09 8:15 [PATCH v2 00/15] mt76: introduce connac3_mac support Lorenzo Bianconi
` (13 preceding siblings ...)
2023-06-09 8:15 ` [PATCH v2 14/15] wifi: mt76: connac: move connac3 definitions in mt76_connac3_mac.h Lorenzo Bianconi
@ 2023-06-09 8:15 ` Lorenzo Bianconi
2023-06-09 16:15 ` Ryder Lee
14 siblings, 1 reply; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-06-09 8:15 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless
Introduce connac3_mac in mt76_connac library to reuse mac code shared
between WiFi7 chipsets.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/Makefile | 2 +-
.../net/wireless/mediatek/mt76/mt76_connac.h | 19 +
.../wireless/mediatek/mt76/mt76_connac3_mac.c | 742 +++++++++++++++++
.../wireless/mediatek/mt76/mt76_connac3_mac.h | 18 +
.../net/wireless/mediatek/mt76/mt7996/init.c | 4 +-
.../net/wireless/mediatek/mt76/mt7996/mac.c | 761 +-----------------
.../net/wireless/mediatek/mt76/mt7996/main.c | 8 +-
.../net/wireless/mediatek/mt76/mt7996/mcu.c | 9 +-
.../wireless/mediatek/mt76/mt7996/mt7996.h | 28 +-
9 files changed, 807 insertions(+), 784 deletions(-)
create mode 100644 drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile
index 84c99b7e57f9..d8e8079c8b54 100644
--- a/drivers/net/wireless/mediatek/mt76/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/Makefile
@@ -27,7 +27,7 @@ mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \
mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
-mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
+mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o mt76_connac3_mac.o
obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
obj-$(CONFIG_MT76x2_COMMON) += mt76x2/
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
index 68bdeada1421..20111678537b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
@@ -415,4 +415,23 @@ void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t,
struct list_head *free_list);
void mt76_connac2_tx_token_put(struct mt76_dev *dev);
+/* connac3 */
+void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi);
+void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv,
+ u8 mode);
+int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev,
+ struct mt76_rx_status *status,
+ struct ieee80211_supported_band *sband,
+ __le32 *rxv, u8 *mode);
+void mt76_connac3_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
+ struct sk_buff *skb, struct mt76_wcid *wcid,
+ struct ieee80211_key_conf *key, int pid,
+ enum mt76_txq_id qid, u32 changed);
+void mt76_connac3_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t,
+ struct ieee80211_sta *sta,
+ struct list_head *free_list);
+void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void *data,
+ u32 max_wtbl_size);
+void mt76_connac3_tx_token_put(struct mt76_dev *dev);
+
#endif /* __MT76_CONNAC_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
new file mode 100644
index 000000000000..4b745bb74ca0
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
@@ -0,0 +1,742 @@
+// SPDX-License-Identifier: ISC
+/* Copyright (C) 2023 MediaTek Inc. */
+
+#include "mt76_connac.h"
+#include "mt76_connac3_mac.h"
+#include "dma.h"
+
+#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f)
+#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\
+ IEEE80211_RADIOTAP_HE_##f)
+
+void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
+{
+ struct mt76_wcid *wcid;
+ u16 fc, tid;
+ u32 val;
+
+ if (!sta ||
+ !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
+ return;
+
+ tid = le32_get_bits(txwi[1], MT_TXD1_TID);
+ if (tid >= 6) /* skip VO queue */
+ return;
+
+ val = le32_to_cpu(txwi[2]);
+ fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
+ FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
+ if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
+ return;
+
+ wcid = (struct mt76_wcid *)sta->drv_priv;
+ if (!test_and_set_bit(tid, &wcid->ampdu_state))
+ ieee80211_start_tx_ba_session(sta, tid, 0);
+}
+EXPORT_SYMBOL_GPL(mt76_connac3_tx_check_aggr);
+
+static void
+mt76_connac3_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
+ struct ieee80211_radiotap_he *he,
+ __le32 *rxv)
+{
+ u32 ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC), offs = 0;
+
+ status->bw = RATE_INFO_BW_HE_RU;
+
+ switch (ru) {
+ case 0 ... 36:
+ status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
+ offs = ru;
+ break;
+ case 37 ... 52:
+ status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
+ offs = ru - 37;
+ break;
+ case 53 ... 60:
+ status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
+ offs = ru - 53;
+ break;
+ case 61 ... 64:
+ status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
+ offs = ru - 61;
+ break;
+ case 65 ... 66:
+ status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
+ offs = ru - 65;
+ break;
+ case 67:
+ status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
+ break;
+ case 68:
+ status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
+ break;
+ }
+
+ he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
+ he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
+ le16_encode_bits(offs,
+ IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
+}
+
+#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f)
+static void
+mt76_connac3_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
+{
+ struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
+ static const struct ieee80211_radiotap_he_mu mu_known = {
+ .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
+ HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
+ HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
+ HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN),
+ .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
+ };
+ struct ieee80211_radiotap_he_mu *he_mu;
+
+ status->flag |= RX_FLAG_RADIOTAP_HE_MU;
+
+ he_mu = skb_push(skb, sizeof(mu_known));
+ memcpy(he_mu, &mu_known, sizeof(mu_known));
+
+ he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
+ if (status->he_dcm)
+ he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm);
+
+ he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
+ MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
+ le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER));
+
+ he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff;
+
+ if (status->bw >= RATE_INFO_BW_40) {
+ he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
+ he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff;
+ }
+
+ if (status->bw >= RATE_INFO_BW_80) {
+ u32 ru_h, ru_l;
+
+ he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff;
+
+ ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L);
+ ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7;
+ he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4);
+ }
+}
+
+void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv,
+ u8 mode)
+{
+ struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
+ static const struct ieee80211_radiotap_he known = {
+ .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
+ HE_BITS(DATA1_DATA_DCM_KNOWN) |
+ HE_BITS(DATA1_STBC_KNOWN) |
+ HE_BITS(DATA1_CODING_KNOWN) |
+ HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
+ HE_BITS(DATA1_DOPPLER_KNOWN) |
+ HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
+ HE_BITS(DATA1_BSS_COLOR_KNOWN),
+ .data2 = HE_BITS(DATA2_GI_KNOWN) |
+ HE_BITS(DATA2_TXBF_KNOWN) |
+ HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
+ HE_BITS(DATA2_TXOP_KNOWN),
+ };
+ u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1;
+ struct ieee80211_radiotap_he *he;
+
+ status->flag |= RX_FLAG_RADIOTAP_HE;
+
+ he = skb_push(skb, sizeof(known));
+ memcpy(he, &known, sizeof(known));
+
+ he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) |
+ HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]);
+ he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]);
+ he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) |
+ le16_encode_bits(ltf_size,
+ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
+ if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
+ he->data5 |= HE_BITS(DATA5_TXBF);
+ he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) |
+ HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]);
+
+ switch (mode) {
+ case MT_PHY_TYPE_HE_SU:
+ he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
+ HE_BITS(DATA1_UL_DL_KNOWN) |
+ HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
+ HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
+
+ he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) |
+ HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
+ break;
+ case MT_PHY_TYPE_HE_EXT_SU:
+ he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
+ HE_BITS(DATA1_UL_DL_KNOWN) |
+ HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
+
+ he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
+ break;
+ case MT_PHY_TYPE_HE_MU:
+ he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
+ HE_BITS(DATA1_UL_DL_KNOWN);
+
+ he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
+ he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]);
+
+ mt76_connac3_mac_decode_he_radiotap_ru(status, he, rxv);
+ mt76_connac3_mac_decode_he_mu_radiotap(skb, rxv);
+ break;
+ case MT_PHY_TYPE_HE_TB:
+ he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
+ HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
+ HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
+ HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
+
+ he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) |
+ HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) |
+ HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) |
+ HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]);
+
+ mt76_connac3_mac_decode_he_radiotap_ru(status, he, rxv);
+ break;
+ default:
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap);
+
+int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev,
+ struct mt76_rx_status *status,
+ struct ieee80211_supported_band *sband,
+ __le32 *rxv, u8 *mode)
+{
+ u8 stbc, gi, bw, dcm, nss;
+ bool cck = false;
+ u32 v0, v2;
+ int i, idx;
+
+ v0 = le32_to_cpu(rxv[0]);
+ v2 = le32_to_cpu(rxv[2]);
+
+ idx = FIELD_GET(MT_PRXV_TX_RATE, v0);
+ i = idx;
+ nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1;
+
+ stbc = FIELD_GET(MT_PRXV_HT_STBC, v2);
+ gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2);
+ *mode = FIELD_GET(MT_PRXV_TX_MODE, v2);
+ dcm = FIELD_GET(MT_PRXV_DCM, v2);
+ bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2);
+
+ switch (*mode) {
+ case MT_PHY_TYPE_CCK:
+ cck = true;
+ fallthrough;
+ case MT_PHY_TYPE_OFDM:
+ i = mt76_get_rate(dev, sband, i, cck);
+ break;
+ case MT_PHY_TYPE_HT_GF:
+ case MT_PHY_TYPE_HT:
+ status->encoding = RX_ENC_HT;
+ if (gi)
+ status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
+ if (i > 31)
+ return -EINVAL;
+ break;
+ case MT_PHY_TYPE_VHT:
+ status->nss = nss;
+ status->encoding = RX_ENC_VHT;
+ if (gi)
+ status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
+ if (i > 11)
+ return -EINVAL;
+ break;
+ case MT_PHY_TYPE_HE_MU:
+ case MT_PHY_TYPE_HE_SU:
+ case MT_PHY_TYPE_HE_EXT_SU:
+ case MT_PHY_TYPE_HE_TB:
+ status->nss = nss;
+ status->encoding = RX_ENC_HE;
+ i &= GENMASK(3, 0);
+
+ if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
+ status->he_gi = gi;
+
+ status->he_dcm = dcm;
+ break;
+ case MT_PHY_TYPE_EHT_SU:
+ case MT_PHY_TYPE_EHT_TRIG:
+ case MT_PHY_TYPE_EHT_MU:
+ status->nss = nss;
+ status->encoding = RX_ENC_EHT;
+ i &= GENMASK(3, 0);
+
+ if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
+ status->eht.gi = gi;
+ break;
+ default:
+ return -EINVAL;
+ }
+ status->rate_idx = i;
+
+ switch (bw) {
+ case IEEE80211_STA_RX_BW_20:
+ break;
+ case IEEE80211_STA_RX_BW_40:
+ if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
+ (idx & MT_PRXV_TX_ER_SU_106T)) {
+ status->bw = RATE_INFO_BW_HE_RU;
+ status->he_ru =
+ NL80211_RATE_INFO_HE_RU_ALLOC_106;
+ } else {
+ status->bw = RATE_INFO_BW_40;
+ }
+ break;
+ case IEEE80211_STA_RX_BW_80:
+ status->bw = RATE_INFO_BW_80;
+ break;
+ case IEEE80211_STA_RX_BW_160:
+ status->bw = RATE_INFO_BW_160;
+ break;
+ case IEEE80211_STA_RX_BW_320:
+ status->bw = RATE_INFO_BW_320;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
+ if (*mode < MT_PHY_TYPE_HE_SU && gi)
+ status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mt76_connac3_mac_fill_rx_rate);
+
+static void
+mt76_connac3_mac_write_txwi_8023(__le32 *txwi, struct sk_buff *skb,
+ struct mt76_wcid *wcid)
+{
+ u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
+ u8 fc_type, fc_stype;
+ u16 ethertype;
+ bool wmm = false;
+ u32 val;
+
+ if (wcid->sta) {
+ struct ieee80211_sta *sta;
+
+ sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
+ wmm = sta->wme;
+ }
+
+ val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
+ FIELD_PREP(MT_TXD1_TID, tid);
+
+ ethertype = get_unaligned_be16(&skb->data[12]);
+ if (ethertype >= ETH_P_802_3_MIN)
+ val |= MT_TXD1_ETH_802_3;
+
+ txwi[1] |= cpu_to_le32(val);
+
+ fc_type = IEEE80211_FTYPE_DATA >> 2;
+ fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0;
+
+ val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
+ FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
+
+ txwi[2] |= cpu_to_le32(val);
+}
+
+static void
+mt76_connac3_mac_write_txwi_80211(struct mt76_dev *dev, __le32 *txwi,
+ struct sk_buff *skb,
+ struct ieee80211_key_conf *key)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ bool multicast = is_multicast_ether_addr(hdr->addr1);
+ u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
+ __le16 fc = hdr->frame_control;
+ u8 fc_type, fc_stype;
+ u32 val;
+
+ if (ieee80211_is_action(fc) &&
+ mgmt->u.action.category == WLAN_CATEGORY_BACK &&
+ mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ)
+ tid = MT_TX_ADDBA;
+ else if (ieee80211_is_mgmt(hdr->frame_control))
+ tid = MT_TX_NORMAL;
+
+ val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
+ FIELD_PREP(MT_TXD1_HDR_INFO,
+ ieee80211_get_hdrlen_from_skb(skb) / 2) |
+ FIELD_PREP(MT_TXD1_TID, tid);
+
+ if (!ieee80211_is_data(fc) || multicast ||
+ info->flags & IEEE80211_TX_CTL_USE_MINRATE)
+ val |= MT_TXD1_FIXED_RATE;
+
+ if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
+ key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
+ val |= MT_TXD1_BIP;
+ txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
+ }
+
+ txwi[1] |= cpu_to_le32(val);
+
+ fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
+ fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
+
+ val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
+ FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
+
+ txwi[2] |= cpu_to_le32(val);
+
+ txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast));
+ if (ieee80211_is_beacon(fc)) {
+ txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT);
+ txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
+ }
+
+ if (info->flags & IEEE80211_TX_CTL_INJECTED) {
+ u16 seqno = le16_to_cpu(hdr->seq_ctrl);
+
+ if (ieee80211_is_back_req(hdr->frame_control)) {
+ struct ieee80211_bar *bar;
+
+ bar = (struct ieee80211_bar *)skb->data;
+ seqno = le16_to_cpu(bar->start_seq_num);
+ }
+
+ val = MT_TXD3_SN_VALID |
+ FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
+ txwi[3] |= cpu_to_le32(val);
+ txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
+ }
+}
+
+void mt76_connac3_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
+ struct sk_buff *skb, struct mt76_wcid *wcid,
+ struct ieee80211_key_conf *key, int pid,
+ enum mt76_txq_id qid, u32 changed)
+{
+ u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE : MT_SDIO_TXD_SIZE;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_vif *vif = info->control.vif;
+ u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
+ u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
+ bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
+ struct mt76_vif *mvif;
+ u16 tx_count = 15;
+ bool beacon = !!(changed & (BSS_CHANGED_BEACON |
+ BSS_CHANGED_BEACON_ENABLED));
+ bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
+ BSS_CHANGED_FILS_DISCOVERY));
+
+ mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL;
+ if (mvif) {
+ omac_idx = mvif->omac_idx;
+ wmm_idx = mvif->wmm_idx;
+ band_idx = mvif->band_idx;
+ }
+
+ if (inband_disc) {
+ p_fmt = MT_TX_TYPE_FW;
+ q_idx = MT_LMAC_ALTX0;
+ } else if (beacon) {
+ p_fmt = MT_TX_TYPE_FW;
+ q_idx = MT_LMAC_BCN0;
+ } else if (qid >= MT_TXQ_PSD) {
+ p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
+ q_idx = MT_LMAC_ALTX0;
+ } else {
+ p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
+ q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS +
+ mt76_connac_lmac_mapping(skb_get_queue_mapping(skb));
+ }
+
+ val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
+ FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
+ FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
+ txwi[0] = cpu_to_le32(val);
+
+ val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
+ FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
+
+ if (band_idx)
+ val |= FIELD_PREP(MT_TXD1_TGID, band_idx);
+
+ txwi[1] = cpu_to_le32(val);
+ txwi[2] = 0;
+
+ val = MT_TXD3_SW_POWER_MGMT |
+ FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count);
+ if (key)
+ val |= MT_TXD3_PROTECT_FRAME;
+ if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+ val |= MT_TXD3_NO_ACK;
+ if (wcid->amsdu)
+ val |= MT_TXD3_HW_AMSDU;
+
+ txwi[3] = cpu_to_le32(val);
+ txwi[4] = 0;
+
+ val = FIELD_PREP(MT_TXD5_PID, pid);
+ if (pid >= MT_PACKET_ID_FIRST)
+ val |= MT_TXD5_TX_STATUS_HOST;
+ txwi[5] = cpu_to_le32(val);
+
+ val = MT_TXD6_DIS_MAT | MT_TXD6_DAS |
+ FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
+ txwi[6] = cpu_to_le32(val);
+ txwi[7] = 0;
+
+ if (is_8023)
+ mt76_connac3_mac_write_txwi_8023(txwi, skb, wcid);
+ else
+ mt76_connac3_mac_write_txwi_80211(dev, txwi, skb, key);
+
+ if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ bool mcast = ieee80211_is_data(hdr->frame_control) &&
+ is_multicast_ether_addr(hdr->addr1);
+ u8 idx = MT76_CONNAC3_BASIC_RATES_TBL;
+
+ if (mvif) {
+ if (mcast && mvif->mcast_rates_idx)
+ idx = mvif->mcast_rates_idx;
+ else if (beacon && mvif->beacon_rates_idx)
+ idx = mvif->beacon_rates_idx;
+ else
+ idx = mvif->basic_rates_idx;
+ }
+
+ txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE, idx));
+ txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
+ }
+}
+EXPORT_SYMBOL_GPL(mt76_connac3_mac_write_txwi);
+
+void mt76_connac3_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t,
+ struct ieee80211_sta *sta,
+ struct list_head *free_list)
+{
+ __le32 *txwi;
+ u16 wcid_idx;
+
+ mt76_connac_txp_skb_unmap(dev, t);
+ if (!t->skb)
+ goto out;
+
+ txwi = (__le32 *)mt76_get_txwi_ptr(dev, t);
+ if (sta) {
+ struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
+
+ wcid_idx = wcid->idx;
+ if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
+ mt76_connac3_tx_check_aggr(sta, txwi);
+ } else {
+ wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
+ }
+
+ __mt76_tx_complete_skb(dev, wcid_idx, t->skb, free_list);
+out:
+ t->skb = NULL;
+ mt76_put_txwi(dev, t);
+}
+EXPORT_SYMBOL_GPL(mt76_connac3_txwi_free);
+
+static bool
+mt76_connac3_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid,
+ int pid, __le32 *txs_data)
+{
+ struct mt76_sta_stats *stats = &wcid->stats;
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_tx_info *info;
+ u32 txrate, txs, mode, stbc;
+ struct rate_info rate = {};
+ struct sk_buff_head list;
+ struct mt76_phy *mphy;
+ struct sk_buff *skb;
+ bool cck = false;
+
+ mt76_tx_status_lock(dev, &list);
+ skb = mt76_tx_status_skb_get(dev, wcid, pid, &list);
+ if (!skb)
+ goto out_no_skb;
+
+ txs = le32_to_cpu(txs_data[0]);
+
+ info = IEEE80211_SKB_CB(skb);
+ if (!(txs & MT_TXS0_ACK_ERROR_MASK))
+ info->flags |= IEEE80211_TX_STAT_ACK;
+
+ info->status.ampdu_len = 1;
+ info->status.ampdu_ack_len = !!(info->flags &
+ IEEE80211_TX_STAT_ACK);
+ info->status.rates[0].idx = -1;
+
+ txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
+
+ rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
+ rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
+ stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC);
+
+ if (stbc && rate.nss > 1)
+ rate.nss >>= 1;
+
+ if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
+ stats->tx_nss[rate.nss - 1]++;
+ if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
+ stats->tx_mcs[rate.mcs]++;
+
+ mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
+ switch (mode) {
+ case MT_PHY_TYPE_CCK:
+ cck = true;
+ fallthrough;
+ case MT_PHY_TYPE_OFDM:
+ mphy = mt76_dev_phy(dev, wcid->phy_idx);
+
+ if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
+ sband = &mphy->sband_5g.sband;
+ else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
+ sband = &mphy->sband_6g.sband;
+ else
+ sband = &mphy->sband_2g.sband;
+
+ rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, cck);
+ rate.legacy = sband->bitrates[rate.mcs].bitrate;
+ break;
+ case MT_PHY_TYPE_HT:
+ case MT_PHY_TYPE_HT_GF:
+ if (rate.mcs > 31)
+ goto out;
+
+ rate.flags = RATE_INFO_FLAGS_MCS;
+ if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
+ rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ break;
+ case MT_PHY_TYPE_VHT:
+ if (rate.mcs > 9)
+ goto out;
+
+ rate.flags = RATE_INFO_FLAGS_VHT_MCS;
+ break;
+ case MT_PHY_TYPE_HE_SU:
+ case MT_PHY_TYPE_HE_EXT_SU:
+ case MT_PHY_TYPE_HE_TB:
+ case MT_PHY_TYPE_HE_MU:
+ if (rate.mcs > 11)
+ goto out;
+
+ rate.he_gi = wcid->rate.he_gi;
+ rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
+ rate.flags = RATE_INFO_FLAGS_HE_MCS;
+ break;
+ case MT_PHY_TYPE_EHT_SU:
+ case MT_PHY_TYPE_EHT_TRIG:
+ case MT_PHY_TYPE_EHT_MU:
+ if (rate.mcs > 13)
+ goto out;
+
+ rate.eht_gi = wcid->rate.eht_gi;
+ rate.flags = RATE_INFO_FLAGS_EHT_MCS;
+ break;
+ default:
+ goto out;
+ }
+
+ stats->tx_mode[mode]++;
+
+ switch (FIELD_GET(MT_TXS0_BW, txs)) {
+ case IEEE80211_STA_RX_BW_320:
+ rate.bw = RATE_INFO_BW_320;
+ stats->tx_bw[4]++;
+ break;
+ case IEEE80211_STA_RX_BW_160:
+ rate.bw = RATE_INFO_BW_160;
+ stats->tx_bw[3]++;
+ break;
+ case IEEE80211_STA_RX_BW_80:
+ rate.bw = RATE_INFO_BW_80;
+ stats->tx_bw[2]++;
+ break;
+ case IEEE80211_STA_RX_BW_40:
+ rate.bw = RATE_INFO_BW_40;
+ stats->tx_bw[1]++;
+ break;
+ default:
+ rate.bw = RATE_INFO_BW_20;
+ stats->tx_bw[0]++;
+ break;
+ }
+ wcid->rate = rate;
+
+out:
+ mt76_tx_status_skb_done(dev, skb, &list);
+
+out_no_skb:
+ mt76_tx_status_unlock(dev, &list);
+
+ return !!skb;
+}
+
+void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void *data,
+ u32 max_wtbl_size)
+{
+ struct mt76_wcid *wcid;
+ __le32 *txs_data = data;
+ u16 wcidx;
+ u8 pid;
+
+ if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
+ return;
+
+ wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
+ pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
+
+ if (pid < MT_PACKET_ID_FIRST)
+ return;
+
+ if (wcidx >= max_wtbl_size)
+ return;
+
+ rcu_read_lock();
+
+ wcid = rcu_dereference(dev->wcid[wcidx]);
+ if (!wcid)
+ goto out;
+
+ mt76_connac3_mac_add_txs_skb(dev, wcid, pid, txs_data);
+ if (!wcid->sta)
+ goto out;
+
+ spin_lock_bh(&dev->sta_poll_lock);
+ if (list_empty(&wcid->poll_list))
+ list_add_tail(&wcid->poll_list, &dev->sta_poll_list);
+ spin_unlock_bh(&dev->sta_poll_lock);
+
+out:
+ rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(mt76_connac3_mac_add_txs);
+
+void mt76_connac3_tx_token_put(struct mt76_dev *dev)
+{
+ struct mt76_txwi_cache *txwi;
+ int id;
+
+ spin_lock_bh(&dev->token_lock);
+ idr_for_each_entry(&dev->token, txwi, id) {
+ mt76_connac3_txwi_free(dev, txwi, NULL, NULL);
+ dev->token_count--;
+ }
+ spin_unlock_bh(&dev->token_lock);
+ idr_destroy(&dev->token);
+}
+EXPORT_SYMBOL_GPL(mt76_connac3_tx_token_put);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
index 6663a0b46541..bcc1d976b2b0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
@@ -4,6 +4,24 @@
#ifndef __MT76_CONNAC3_MAC_H
#define __MT76_CONNAC3_MAC_H
+/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
+#define MT76_CONNAC3_BASIC_RATES_TBL 11
+#define MT76_CONNAC3_BEACON_RATES_TBL 25
+
+enum {
+ MT_CTX0,
+ MT_HIF0 = 0x0,
+
+ MT_LMAC_AC00 = 0x0,
+ MT_LMAC_AC01,
+ MT_LMAC_AC02,
+ MT_LMAC_AC03,
+ MT_LMAC_ALTX0 = 0x10,
+ MT_LMAC_BMC0,
+ MT_LMAC_BCN0,
+ MT_LMAC_PSMP0,
+};
+
#define MT_CT_PARSE_LEN 72
#define MT_CT_DMA_BUF_NUM 2
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
index 8f3536dbe2bb..b4a2ae00d7e0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
@@ -262,7 +262,7 @@ static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) {
u16 rate = mt76_rates[i].hw_value;
- u16 idx = MT7996_BASIC_RATES_TBL + i;
+ u16 idx = MT76_CONNAC3_BASIC_RATES_TBL + i;
rate = FIELD_PREP(MT_TX_RATE_MODE, rate >> 8) |
FIELD_PREP(MT_TX_RATE_IDX, rate & GENMASK(7, 0));
@@ -903,7 +903,7 @@ void mt7996_unregister_device(struct mt7996_dev *dev)
mt7996_coredump_unregister(dev);
mt76_unregister_device(&dev->mt76);
mt7996_mcu_exit(dev);
- mt7996_tx_token_put(dev);
+ mt76_connac3_tx_token_put(&dev->mt76);
mt7996_dma_cleanup(dev);
tasklet_disable(&dev->mt76.irq_tasklet);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index e407fc547e42..2ad2d8994edf 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -13,10 +13,6 @@
#define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2)
-#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f)
-#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\
- IEEE80211_RADIOTAP_HE_##f)
-
static const struct mt7996_dfs_radar_spec etsi_radar_specs = {
.pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
.radar_pattern = {
@@ -263,180 +259,6 @@ void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
mt76_wr(dev, MT_WTBL_ITCR, ctrl);
}
-static void
-mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
- struct ieee80211_radiotap_he *he,
- __le32 *rxv)
-{
- u32 ru, offs = 0;
-
- ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC);
-
- status->bw = RATE_INFO_BW_HE_RU;
-
- switch (ru) {
- case 0 ... 36:
- status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
- offs = ru;
- break;
- case 37 ... 52:
- status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
- offs = ru - 37;
- break;
- case 53 ... 60:
- status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
- offs = ru - 53;
- break;
- case 61 ... 64:
- status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
- offs = ru - 61;
- break;
- case 65 ... 66:
- status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
- offs = ru - 65;
- break;
- case 67:
- status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
- break;
- case 68:
- status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
- break;
- }
-
- he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
- he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
- le16_encode_bits(offs,
- IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
-}
-
-static void
-mt7996_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
-{
- struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
- static const struct ieee80211_radiotap_he_mu mu_known = {
- .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
- HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
- HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
- HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN),
- .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
- };
- struct ieee80211_radiotap_he_mu *he_mu = NULL;
-
- status->flag |= RX_FLAG_RADIOTAP_HE_MU;
-
- he_mu = skb_push(skb, sizeof(mu_known));
- memcpy(he_mu, &mu_known, sizeof(mu_known));
-
-#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f)
-
- he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
- if (status->he_dcm)
- he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm);
-
- he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
- MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
- le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER));
-
- he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff;
-
- if (status->bw >= RATE_INFO_BW_40) {
- he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
- he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff;
- }
-
- if (status->bw >= RATE_INFO_BW_80) {
- u32 ru_h, ru_l;
-
- he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff;
-
- ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L);
- ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7;
- he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4);
- }
-}
-
-static void
-mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode)
-{
- struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
- static const struct ieee80211_radiotap_he known = {
- .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
- HE_BITS(DATA1_DATA_DCM_KNOWN) |
- HE_BITS(DATA1_STBC_KNOWN) |
- HE_BITS(DATA1_CODING_KNOWN) |
- HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
- HE_BITS(DATA1_DOPPLER_KNOWN) |
- HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
- HE_BITS(DATA1_BSS_COLOR_KNOWN),
- .data2 = HE_BITS(DATA2_GI_KNOWN) |
- HE_BITS(DATA2_TXBF_KNOWN) |
- HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
- HE_BITS(DATA2_TXOP_KNOWN),
- };
- struct ieee80211_radiotap_he *he = NULL;
- u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1;
-
- status->flag |= RX_FLAG_RADIOTAP_HE;
-
- he = skb_push(skb, sizeof(known));
- memcpy(he, &known, sizeof(known));
-
- he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) |
- HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]);
- he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]);
- he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) |
- le16_encode_bits(ltf_size,
- IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
- if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
- he->data5 |= HE_BITS(DATA5_TXBF);
- he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) |
- HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]);
-
- switch (mode) {
- case MT_PHY_TYPE_HE_SU:
- he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
- HE_BITS(DATA1_UL_DL_KNOWN) |
- HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
- HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
-
- he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) |
- HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
- break;
- case MT_PHY_TYPE_HE_EXT_SU:
- he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
- HE_BITS(DATA1_UL_DL_KNOWN) |
- HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
-
- he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
- break;
- case MT_PHY_TYPE_HE_MU:
- he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
- HE_BITS(DATA1_UL_DL_KNOWN);
-
- he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
- he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]);
-
- mt7996_mac_decode_he_radiotap_ru(status, he, rxv);
- mt7996_mac_decode_he_mu_radiotap(skb, rxv);
- break;
- case MT_PHY_TYPE_HE_TB:
- he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
- HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
- HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
- HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
-
- he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) |
- HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) |
- HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) |
- HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]);
-
- mt7996_mac_decode_he_radiotap_ru(status, he, rxv);
- break;
- default:
- break;
- }
-}
-
/* The HW does not translate the mac header to 802.3 for mesh point */
static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
{
@@ -517,114 +339,6 @@ static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
return 0;
}
-static int
-mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
- struct mt76_rx_status *status,
- struct ieee80211_supported_band *sband,
- __le32 *rxv, u8 *mode)
-{
- u32 v0, v2;
- u8 stbc, gi, bw, dcm, nss;
- int i, idx;
- bool cck = false;
-
- v0 = le32_to_cpu(rxv[0]);
- v2 = le32_to_cpu(rxv[2]);
-
- idx = FIELD_GET(MT_PRXV_TX_RATE, v0);
- i = idx;
- nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1;
-
- stbc = FIELD_GET(MT_PRXV_HT_STBC, v2);
- gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2);
- *mode = FIELD_GET(MT_PRXV_TX_MODE, v2);
- dcm = FIELD_GET(MT_PRXV_DCM, v2);
- bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2);
-
- switch (*mode) {
- case MT_PHY_TYPE_CCK:
- cck = true;
- fallthrough;
- case MT_PHY_TYPE_OFDM:
- i = mt76_get_rate(&dev->mt76, sband, i, cck);
- break;
- case MT_PHY_TYPE_HT_GF:
- case MT_PHY_TYPE_HT:
- status->encoding = RX_ENC_HT;
- if (gi)
- status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
- if (i > 31)
- return -EINVAL;
- break;
- case MT_PHY_TYPE_VHT:
- status->nss = nss;
- status->encoding = RX_ENC_VHT;
- if (gi)
- status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
- if (i > 11)
- return -EINVAL;
- break;
- case MT_PHY_TYPE_HE_MU:
- case MT_PHY_TYPE_HE_SU:
- case MT_PHY_TYPE_HE_EXT_SU:
- case MT_PHY_TYPE_HE_TB:
- status->nss = nss;
- status->encoding = RX_ENC_HE;
- i &= GENMASK(3, 0);
-
- if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
- status->he_gi = gi;
-
- status->he_dcm = dcm;
- break;
- case MT_PHY_TYPE_EHT_SU:
- case MT_PHY_TYPE_EHT_TRIG:
- case MT_PHY_TYPE_EHT_MU:
- status->nss = nss;
- status->encoding = RX_ENC_EHT;
- i &= GENMASK(3, 0);
-
- if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
- status->eht.gi = gi;
- break;
- default:
- return -EINVAL;
- }
- status->rate_idx = i;
-
- switch (bw) {
- case IEEE80211_STA_RX_BW_20:
- break;
- case IEEE80211_STA_RX_BW_40:
- if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
- (idx & MT_PRXV_TX_ER_SU_106T)) {
- status->bw = RATE_INFO_BW_HE_RU;
- status->he_ru =
- NL80211_RATE_INFO_HE_RU_ALLOC_106;
- } else {
- status->bw = RATE_INFO_BW_40;
- }
- break;
- case IEEE80211_STA_RX_BW_80:
- status->bw = RATE_INFO_BW_80;
- break;
- case IEEE80211_STA_RX_BW_160:
- status->bw = RATE_INFO_BW_160;
- break;
- case IEEE80211_STA_RX_BW_320:
- status->bw = RATE_INFO_BW_320;
- break;
- default:
- return -EINVAL;
- }
-
- status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
- if (*mode < MT_PHY_TYPE_HE_SU && gi)
- status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
-
- return 0;
-}
-
static int
mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
{
@@ -814,7 +528,8 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
return -EINVAL;
}
- ret = mt7996_mac_fill_rx_rate(dev, status, sband, rxv, &mode);
+ ret = mt76_connac3_mac_fill_rx_rate(&dev->mt76, status, sband,
+ rxv, &mode);
if (ret < 0)
return ret;
}
@@ -882,7 +597,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
}
if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
- mt7996_mac_decode_he_radiotap(skb, rxv, mode);
+ mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode);
if (!status->wcid || !ieee80211_is_data_qos(fc))
return 0;
@@ -895,210 +610,6 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
return 0;
}
-static void
-mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi,
- struct sk_buff *skb, struct mt76_wcid *wcid)
-{
- u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
- u8 fc_type, fc_stype;
- u16 ethertype;
- bool wmm = false;
- u32 val;
-
- if (wcid->sta) {
- struct ieee80211_sta *sta;
-
- sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
- wmm = sta->wme;
- }
-
- val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
- FIELD_PREP(MT_TXD1_TID, tid);
-
- ethertype = get_unaligned_be16(&skb->data[12]);
- if (ethertype >= ETH_P_802_3_MIN)
- val |= MT_TXD1_ETH_802_3;
-
- txwi[1] |= cpu_to_le32(val);
-
- fc_type = IEEE80211_FTYPE_DATA >> 2;
- fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0;
-
- val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
- FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
-
- txwi[2] |= cpu_to_le32(val);
-}
-
-static void
-mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
- struct sk_buff *skb, struct ieee80211_key_conf *key)
-{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- bool multicast = is_multicast_ether_addr(hdr->addr1);
- u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
- __le16 fc = hdr->frame_control;
- u8 fc_type, fc_stype;
- u32 val;
-
- if (ieee80211_is_action(fc) &&
- mgmt->u.action.category == WLAN_CATEGORY_BACK &&
- mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ)
- tid = MT_TX_ADDBA;
- else if (ieee80211_is_mgmt(hdr->frame_control))
- tid = MT_TX_NORMAL;
-
- val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
- FIELD_PREP(MT_TXD1_HDR_INFO,
- ieee80211_get_hdrlen_from_skb(skb) / 2) |
- FIELD_PREP(MT_TXD1_TID, tid);
-
- if (!ieee80211_is_data(fc) || multicast ||
- info->flags & IEEE80211_TX_CTL_USE_MINRATE)
- val |= MT_TXD1_FIXED_RATE;
-
- if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
- key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
- val |= MT_TXD1_BIP;
- txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
- }
-
- txwi[1] |= cpu_to_le32(val);
-
- fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
- fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
-
- val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
- FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
-
- txwi[2] |= cpu_to_le32(val);
-
- txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast));
- if (ieee80211_is_beacon(fc)) {
- txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT);
- txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
- }
-
- if (info->flags & IEEE80211_TX_CTL_INJECTED) {
- u16 seqno = le16_to_cpu(hdr->seq_ctrl);
-
- if (ieee80211_is_back_req(hdr->frame_control)) {
- struct ieee80211_bar *bar;
-
- bar = (struct ieee80211_bar *)skb->data;
- seqno = le16_to_cpu(bar->start_seq_num);
- }
-
- val = MT_TXD3_SN_VALID |
- FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
- txwi[3] |= cpu_to_le32(val);
- txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
- }
-}
-
-void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
- struct sk_buff *skb, struct mt76_wcid *wcid,
- struct ieee80211_key_conf *key, int pid,
- enum mt76_txq_id qid, u32 changed)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_vif *vif = info->control.vif;
- u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
- u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
- bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
- struct mt76_vif *mvif;
- u16 tx_count = 15;
- u32 val;
- bool beacon = !!(changed & (BSS_CHANGED_BEACON |
- BSS_CHANGED_BEACON_ENABLED));
- bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
- BSS_CHANGED_FILS_DISCOVERY));
-
- mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL;
- if (mvif) {
- omac_idx = mvif->omac_idx;
- wmm_idx = mvif->wmm_idx;
- band_idx = mvif->band_idx;
- }
-
- if (inband_disc) {
- p_fmt = MT_TX_TYPE_FW;
- q_idx = MT_LMAC_ALTX0;
- } else if (beacon) {
- p_fmt = MT_TX_TYPE_FW;
- q_idx = MT_LMAC_BCN0;
- } else if (qid >= MT_TXQ_PSD) {
- p_fmt = MT_TX_TYPE_CT;
- q_idx = MT_LMAC_ALTX0;
- } else {
- p_fmt = MT_TX_TYPE_CT;
- q_idx = wmm_idx * MT7996_MAX_WMM_SETS +
- mt76_connac_lmac_mapping(skb_get_queue_mapping(skb));
- }
-
- val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) |
- FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
- FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
- txwi[0] = cpu_to_le32(val);
-
- val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
- FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
-
- if (band_idx)
- val |= FIELD_PREP(MT_TXD1_TGID, band_idx);
-
- txwi[1] = cpu_to_le32(val);
- txwi[2] = 0;
-
- val = MT_TXD3_SW_POWER_MGMT |
- FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count);
- if (key)
- val |= MT_TXD3_PROTECT_FRAME;
- if (info->flags & IEEE80211_TX_CTL_NO_ACK)
- val |= MT_TXD3_NO_ACK;
- if (wcid->amsdu)
- val |= MT_TXD3_HW_AMSDU;
-
- txwi[3] = cpu_to_le32(val);
- txwi[4] = 0;
-
- val = FIELD_PREP(MT_TXD5_PID, pid);
- if (pid >= MT_PACKET_ID_FIRST)
- val |= MT_TXD5_TX_STATUS_HOST;
- txwi[5] = cpu_to_le32(val);
-
- val = MT_TXD6_DIS_MAT | MT_TXD6_DAS |
- FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
- txwi[6] = cpu_to_le32(val);
- txwi[7] = 0;
-
- if (is_8023)
- mt7996_mac_write_txwi_8023(dev, txwi, skb, wcid);
- else
- mt7996_mac_write_txwi_80211(dev, txwi, skb, key);
-
- if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- bool mcast = ieee80211_is_data(hdr->frame_control) &&
- is_multicast_ether_addr(hdr->addr1);
- u8 idx = MT7996_BASIC_RATES_TBL;
-
- if (mvif) {
- if (mcast && mvif->mcast_rates_idx)
- idx = mvif->mcast_rates_idx;
- else if (beacon && mvif->beacon_rates_idx)
- idx = mvif->beacon_rates_idx;
- else
- idx = mvif->basic_rates_idx;
- }
-
- txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE, idx));
- txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
- }
-}
-
int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
@@ -1138,8 +649,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
return id;
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
- mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
- pid, qid, 0);
+ mt76_connac3_mac_write_txwi(mdev, txwi_ptr, tx_info->skb, wcid, key,
+ pid, qid, 0);
txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
for (i = 0; i < nbuf; i++) {
@@ -1178,62 +689,6 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
return 0;
}
-static void
-mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
-{
- struct mt7996_sta *msta;
- u16 fc, tid;
- u32 val;
-
- if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
- return;
-
- tid = le32_get_bits(txwi[1], MT_TXD1_TID);
- if (tid >= 6) /* skip VO queue */
- return;
-
- val = le32_to_cpu(txwi[2]);
- fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
- FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
- if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
- return;
-
- msta = (struct mt7996_sta *)sta->drv_priv;
- if (!test_and_set_bit(tid, &msta->wcid.ampdu_state))
- ieee80211_start_tx_ba_session(sta, tid, 0);
-}
-
-static void
-mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
- struct ieee80211_sta *sta, struct list_head *free_list)
-{
- struct mt76_dev *mdev = &dev->mt76;
- struct mt76_wcid *wcid;
- __le32 *txwi;
- u16 wcid_idx;
-
- mt76_connac_txp_skb_unmap(mdev, t);
- if (!t->skb)
- goto out;
-
- txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t);
- if (sta) {
- wcid = (struct mt76_wcid *)sta->drv_priv;
- wcid_idx = wcid->idx;
-
- if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
- mt7996_tx_check_aggr(sta, txwi);
- } else {
- wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
- }
-
- __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
-
-out:
- t->skb = NULL;
- mt76_put_txwi(mdev, t);
-}
-
static void
mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
{
@@ -1308,7 +763,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
if (!txwi)
continue;
- mt7996_txwi_free(dev, txwi, sta, &free_list);
+ mt76_connac3_txwi_free(mdev, txwi, sta, &free_list);
}
}
@@ -1325,186 +780,6 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
}
}
-static bool
-mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
- int pid, __le32 *txs_data)
-{
- struct mt76_sta_stats *stats = &wcid->stats;
- struct ieee80211_supported_band *sband;
- struct mt76_dev *mdev = &dev->mt76;
- struct mt76_phy *mphy;
- struct ieee80211_tx_info *info;
- struct sk_buff_head list;
- struct rate_info rate = {};
- struct sk_buff *skb;
- bool cck = false;
- u32 txrate, txs, mode, stbc;
-
- mt76_tx_status_lock(mdev, &list);
- skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
- if (!skb)
- goto out_no_skb;
-
- txs = le32_to_cpu(txs_data[0]);
-
- info = IEEE80211_SKB_CB(skb);
- if (!(txs & MT_TXS0_ACK_ERROR_MASK))
- info->flags |= IEEE80211_TX_STAT_ACK;
-
- info->status.ampdu_len = 1;
- info->status.ampdu_ack_len = !!(info->flags &
- IEEE80211_TX_STAT_ACK);
-
- info->status.rates[0].idx = -1;
-
- txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
-
- rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
- rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
- stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC);
-
- if (stbc && rate.nss > 1)
- rate.nss >>= 1;
-
- if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
- stats->tx_nss[rate.nss - 1]++;
- if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
- stats->tx_mcs[rate.mcs]++;
-
- mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
- switch (mode) {
- case MT_PHY_TYPE_CCK:
- cck = true;
- fallthrough;
- case MT_PHY_TYPE_OFDM:
- mphy = mt76_dev_phy(mdev, wcid->phy_idx);
-
- if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
- sband = &mphy->sband_5g.sband;
- else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
- sband = &mphy->sband_6g.sband;
- else
- sband = &mphy->sband_2g.sband;
-
- rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, cck);
- rate.legacy = sband->bitrates[rate.mcs].bitrate;
- break;
- case MT_PHY_TYPE_HT:
- case MT_PHY_TYPE_HT_GF:
- if (rate.mcs > 31)
- goto out;
-
- rate.flags = RATE_INFO_FLAGS_MCS;
- if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
- rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
- break;
- case MT_PHY_TYPE_VHT:
- if (rate.mcs > 9)
- goto out;
-
- rate.flags = RATE_INFO_FLAGS_VHT_MCS;
- break;
- case MT_PHY_TYPE_HE_SU:
- case MT_PHY_TYPE_HE_EXT_SU:
- case MT_PHY_TYPE_HE_TB:
- case MT_PHY_TYPE_HE_MU:
- if (rate.mcs > 11)
- goto out;
-
- rate.he_gi = wcid->rate.he_gi;
- rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
- rate.flags = RATE_INFO_FLAGS_HE_MCS;
- break;
- case MT_PHY_TYPE_EHT_SU:
- case MT_PHY_TYPE_EHT_TRIG:
- case MT_PHY_TYPE_EHT_MU:
- if (rate.mcs > 13)
- goto out;
-
- rate.eht_gi = wcid->rate.eht_gi;
- rate.flags = RATE_INFO_FLAGS_EHT_MCS;
- break;
- default:
- goto out;
- }
-
- stats->tx_mode[mode]++;
-
- switch (FIELD_GET(MT_TXS0_BW, txs)) {
- case IEEE80211_STA_RX_BW_320:
- rate.bw = RATE_INFO_BW_320;
- stats->tx_bw[4]++;
- break;
- case IEEE80211_STA_RX_BW_160:
- rate.bw = RATE_INFO_BW_160;
- stats->tx_bw[3]++;
- break;
- case IEEE80211_STA_RX_BW_80:
- rate.bw = RATE_INFO_BW_80;
- stats->tx_bw[2]++;
- break;
- case IEEE80211_STA_RX_BW_40:
- rate.bw = RATE_INFO_BW_40;
- stats->tx_bw[1]++;
- break;
- default:
- rate.bw = RATE_INFO_BW_20;
- stats->tx_bw[0]++;
- break;
- }
- wcid->rate = rate;
-
-out:
- mt76_tx_status_skb_done(mdev, skb, &list);
-
-out_no_skb:
- mt76_tx_status_unlock(mdev, &list);
-
- return !!skb;
-}
-
-static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
-{
- struct mt7996_sta *msta = NULL;
- struct mt76_wcid *wcid;
- __le32 *txs_data = data;
- u16 wcidx;
- u8 pid;
-
- if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
- return;
-
- wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
- pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
-
- if (pid < MT_PACKET_ID_FIRST)
- return;
-
- if (wcidx >= mt7996_wtbl_size(dev))
- return;
-
- rcu_read_lock();
-
- wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
- if (!wcid)
- goto out;
-
- msta = container_of(wcid, struct mt7996_sta, wcid);
-
- mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data);
-
- if (!wcid->sta)
- goto out;
-
- spin_lock_bh(&dev->mt76.sta_poll_lock);
- if (list_empty(&msta->wcid.poll_list))
- list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list);
- spin_unlock_bh(&dev->mt76.sta_poll_lock);
-
-out:
- rcu_read_unlock();
-}
-
bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len)
{
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
@@ -1527,7 +802,8 @@ bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len)
return false;
case PKT_TYPE_TXS:
for (rxd += 4; rxd + 8 <= end; rxd += 8)
- mt7996_mac_add_txs(dev, rxd);
+ mt76_connac3_mac_add_txs(mdev, rxd,
+ mt7996_wtbl_size(dev));
return false;
case PKT_TYPE_RX_FW_MONITOR:
mt7996_debugfs_rx_fw_monitor(dev, data, len);
@@ -1564,7 +840,8 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
break;
case PKT_TYPE_TXS:
for (rxd += 4; rxd + 8 <= end; rxd += 8)
- mt7996_mac_add_txs(dev, rxd);
+ mt76_connac3_mac_add_txs(mdev, rxd,
+ mt7996_wtbl_size(dev));
dev_kfree_skb(skb);
break;
case PKT_TYPE_RX_FW_MONITOR:
@@ -1771,20 +1048,6 @@ mt7996_update_beacons(struct mt7996_dev *dev)
mt7996_update_vif_beacon, phy3->hw);
}
-void mt7996_tx_token_put(struct mt7996_dev *dev)
-{
- struct mt76_txwi_cache *txwi;
- int id;
-
- spin_lock_bh(&dev->mt76.token_lock);
- idr_for_each_entry(&dev->mt76.token, txwi, id) {
- mt7996_txwi_free(dev, txwi, NULL, NULL);
- dev->mt76.token_count--;
- }
- spin_unlock_bh(&dev->mt76.token_lock);
- idr_destroy(&dev->mt76.token);
-}
-
static int
mt7996_mac_restart(struct mt7996_dev *dev)
{
@@ -1834,7 +1097,7 @@ mt7996_mac_restart(struct mt7996_dev *dev)
napi_disable(&dev->mt76.tx_napi);
/* token reinit */
- mt7996_tx_token_put(dev);
+ mt76_connac3_tx_token_put(&dev->mt76);
idr_init(&dev->mt76.token);
mt7996_dma_reset(dev, true);
@@ -2042,7 +1305,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
mt7996_dma_reset(dev, false);
- mt7996_tx_token_put(dev);
+ mt76_connac3_tx_token_put(&dev->mt76);
idr_init(&dev->mt76.token);
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index ee9e409b8eb9..6aef12e5dfe4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -221,9 +221,9 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ)
- mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL + 4;
+ mvif->mt76.basic_rates_idx = MT76_CONNAC3_BASIC_RATES_TBL + 4;
else
- mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL;
+ mvif->mt76.basic_rates_idx = MT76_CONNAC3_BASIC_RATES_TBL;
mt7996_init_bitrate_mask(vif);
@@ -518,7 +518,7 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct mt7996_dev *dev = mt7996_hw_dev(hw);
/* must odd index */
- idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->idx % 20);
+ idx = MT76_CONNAC3_BEACON_RATES_TBL + 2 * (mvif->idx % 20);
mt7996_mac_set_fixed_rate_table(dev, idx, rate);
return idx;
}
@@ -526,7 +526,7 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
idx = FIELD_GET(MT_TX_RATE_IDX, rate);
for (i = 0; i < ARRAY_SIZE(mt76_rates); i++)
if ((mt76_rates[i].hw_value & GENMASK(7, 0)) == idx)
- return MT7996_BASIC_RATES_TBL + i;
+ return MT76_CONNAC3_BASIC_RATES_TBL + i;
return mvif->basic_rates_idx;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 6cc87835263a..d0ba58c58760 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -1912,8 +1912,8 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
}
buf = (u8 *)bcn + sizeof(*bcn) - MAX_BEACON_SIZE;
- mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0,
- BSS_CHANGED_BEACON);
+ mt76_connac3_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid, NULL,
+ 0, 0, BSS_CHANGED_BEACON);
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
}
@@ -2024,7 +2024,8 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
buf = (u8 *)tlv + sizeof(*discov) - MAX_INBAND_FRAME_SIZE;
- mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0, changed);
+ mt76_connac3_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid,
+ NULL, 0, 0, changed);
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
@@ -2575,7 +2576,7 @@ int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif)
e = (struct edca *)tlv;
e->set = WMM_PARAM_SET;
- e->queue = ac + mvif->mt76.wmm_idx * MT7996_MAX_WMM_SETS;
+ e->queue = ac + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS;
e->aifs = q->aifs;
e->txop = cpu_to_le16(q->txop);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index c8e8a04a561e..1de85e0a8b32 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -12,7 +12,6 @@
#include "regs.h"
#define MT7996_MAX_INTERFACES 19 /* per-band */
-#define MT7996_MAX_WMM_SETS 4
#define MT7996_WTBL_RESERVED (mt7996_wtbl_size(dev) - 1)
#define MT7996_WTBL_STA (MT7996_WTBL_RESERVED - \
mt7996_max_interface_num(dev))
@@ -43,10 +42,6 @@
#define MT7996_MAX_STA_TWT_AGRT 8
#define MT7996_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 3)
-/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
-#define MT7996_BASIC_RATES_TBL 11
-#define MT7996_BEACON_RATES_TBL 25
-
struct mt7996_vif;
struct mt7996_sta;
struct mt7996_dfs_pulse;
@@ -300,20 +295,6 @@ enum {
__MT_WFDMA_MAX,
};
-enum {
- MT_CTX0,
- MT_HIF0 = 0x0,
-
- MT_LMAC_AC00 = 0x0,
- MT_LMAC_AC01,
- MT_LMAC_AC02,
- MT_LMAC_AC03,
- MT_LMAC_ALTX0 = 0x10,
- MT_LMAC_BMC0,
- MT_LMAC_BCN0,
- MT_LMAC_PSMP0,
-};
-
enum {
MT_RX_SEL0,
MT_RX_SEL1,
@@ -505,10 +486,10 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
struct ieee80211_vif *vif, bool enable);
void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
u8 tbl_idx, u16 rate_idx);
-void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
- struct sk_buff *skb, struct mt76_wcid *wcid,
- struct ieee80211_key_conf *key, int pid,
- enum mt76_txq_id qid, u32 changed);
+void mt76_connac3_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
+ struct sk_buff *skb, struct mt76_wcid *wcid,
+ struct ieee80211_key_conf *key, int pid,
+ enum mt76_txq_id qid, u32 changed);
void mt7996_mac_set_timing(struct mt7996_phy *phy);
int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
@@ -529,7 +510,6 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info);
-void mt7996_tx_token_put(struct mt7996_dev *dev);
void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb, u32 *info);
bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len);
--
2.40.1
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library
2023-06-09 8:15 ` [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library Lorenzo Bianconi
@ 2023-06-09 16:15 ` Ryder Lee
2023-06-09 16:34 ` lorenzo.bianconi
0 siblings, 1 reply; 27+ messages in thread
From: Ryder Lee @ 2023-06-09 16:15 UTC (permalink / raw)
To: nbd@nbd.name, lorenzo@kernel.org
Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org
On Fri, 2023-06-09 at 10:15 +0200, Lorenzo Bianconi wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> Introduce connac3_mac in mt76_connac library to reuse mac code
> shared
> between WiFi7 chipsets.
>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/wireless/mediatek/mt76/Makefile | 2 +-
> .../net/wireless/mediatek/mt76/mt76_connac.h | 19 +
> .../wireless/mediatek/mt76/mt76_connac3_mac.c | 742
> +++++++++++++++++
> .../wireless/mediatek/mt76/mt76_connac3_mac.h | 18 +
> .../net/wireless/mediatek/mt76/mt7996/init.c | 4 +-
> .../net/wireless/mediatek/mt76/mt7996/mac.c | 761 +---------------
> --
> .../net/wireless/mediatek/mt76/mt7996/main.c | 8 +-
> .../net/wireless/mediatek/mt76/mt7996/mcu.c | 9 +-
> .../wireless/mediatek/mt76/mt7996/mt7996.h | 28 +-
> 9 files changed, 807 insertions(+), 784 deletions(-)
> create mode 100644
> drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
>
> diff --git a/drivers/net/wireless/mediatek/mt76/Makefile
> b/drivers/net/wireless/mediatek/mt76/Makefile
> index 84c99b7e57f9..d8e8079c8b54 100644
> --- a/drivers/net/wireless/mediatek/mt76/Makefile
> +++ b/drivers/net/wireless/mediatek/mt76/Makefile
> @@ -27,7 +27,7 @@ mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o
> mt76x02_mcu.o \
>
> mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
>
> -mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
> +mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
> mt76_connac3_mac.o
>
> obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
> obj-$(CONFIG_MT76x2_COMMON) += mt76x2/
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> index 68bdeada1421..20111678537b 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> @@ -415,4 +415,23 @@ void mt76_connac2_txwi_free(struct mt76_dev
> *dev, struct mt76_txwi_cache *t,
> struct list_head *free_list);
> void mt76_connac2_tx_token_put(struct mt76_dev *dev);
>
> +/* connac3 */
> +void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta, __le32
> *txwi);
> +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32
> *rxv,
> + u8 mode);
> +int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev,
> + struct mt76_rx_status *status,
> + struct ieee80211_supported_band
> *sband,
> + __le32 *rxv, u8 *mode);
> +void mt76_connac3_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
> + struct sk_buff *skb, struct mt76_wcid
> *wcid,
> + struct ieee80211_key_conf *key, int
> pid,
> + enum mt76_txq_id qid, u32 changed);
> +void mt76_connac3_txwi_free(struct mt76_dev *dev, struct
> mt76_txwi_cache *t,
> + struct ieee80211_sta *sta,
> + struct list_head *free_list);
> +void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void *data,
> + u32 max_wtbl_size);
> +void mt76_connac3_tx_token_put(struct mt76_dev *dev);
> +
> #endif /* __MT76_CONNAC_H */
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> new file mode 100644
> index 000000000000..4b745bb74ca0
> --- /dev/null
> +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> @@ -0,0 +1,742 @@
> +// SPDX-License-Identifier: ISC
> +/* Copyright (C) 2023 MediaTek Inc. */
> +
> +#include "mt76_connac.h"
> +#include "mt76_connac3_mac.h"
> +#include "dma.h"
> +
> +#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f)
> +#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v,
> MT_CRXV_HE_##m),\
> + IEEE80211_RADIOTAP_HE_
> ##f)
> +
> +void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta, __le32
> *txwi)
> +{
> + struct mt76_wcid *wcid;
> + u16 fc, tid;
> + u32 val;
> +
> + if (!sta ||
> + !(sta->deflink.ht_cap.ht_supported || sta-
> >deflink.he_cap.has_he))
> + return;
> +
> + tid = le32_get_bits(txwi[1], MT_TXD1_TID);
> + if (tid >= 6) /* skip VO queue */
> + return;
> +
> + val = le32_to_cpu(txwi[2]);
> + fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
> + FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
> + if (unlikely(fc != (IEEE80211_FTYPE_DATA |
> IEEE80211_STYPE_QOS_DATA)))
> + return;
> +
> + wcid = (struct mt76_wcid *)sta->drv_priv;
> + if (!test_and_set_bit(tid, &wcid->ampdu_state))
> + ieee80211_start_tx_ba_session(sta, tid, 0);
> +}
> +EXPORT_SYMBOL_GPL(mt76_connac3_tx_check_aggr);
> +
> +static void
> +mt76_connac3_mac_decode_he_radiotap_ru(struct mt76_rx_status
> *status,
> + struct ieee80211_radiotap_he
> *he,
> + __le32 *rxv)
> +{
> + u32 ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC), offs = 0;
> +
> + status->bw = RATE_INFO_BW_HE_RU;
> +
> + switch (ru) {
> + case 0 ... 36:
> + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
> + offs = ru;
> + break;
> + case 37 ... 52:
> + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
> + offs = ru - 37;
> + break;
> + case 53 ... 60:
> + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
> + offs = ru - 53;
> + break;
> + case 61 ... 64:
> + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
> + offs = ru - 61;
> + break;
> + case 65 ... 66:
> + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
> + offs = ru - 65;
> + break;
> + case 67:
> + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
> + break;
> + case 68:
> + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
> + break;
> + }
> +
> + he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> + he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
> + le16_encode_bits(offs,
> + IEEE80211_RADIOTAP_HE_DATA2_RU_OF
> FSET);
> +}
> +
> +#define MU_PREP(f, v) le16_encode_bits(v,
> IEEE80211_RADIOTAP_HE_MU_##f)
> +static void
> +mt76_connac3_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32
> *rxv)
> +{
> + struct mt76_rx_status *status = (struct mt76_rx_status *)skb-
> >cb;
> + static const struct ieee80211_radiotap_he_mu mu_known = {
> + .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
> + HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
> + HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
> + HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN),
> + .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
> + };
> + struct ieee80211_radiotap_he_mu *he_mu;
> +
> + status->flag |= RX_FLAG_RADIOTAP_HE_MU;
> +
> + he_mu = skb_push(skb, sizeof(mu_known));
> + memcpy(he_mu, &mu_known, sizeof(mu_known));
> +
> + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
> + if (status->he_dcm)
> + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status-
> >he_dcm);
> +
> + he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
> + MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
> + le32_get_bits(rxv[4],
> MT_CRXV_HE_NUM_USER));
> +
> + he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) &
> 0xff;
> +
> + if (status->bw >= RATE_INFO_BW_40) {
> + he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
> + he_mu->ru_ch2[0] = le32_get_bits(rxv[16],
> MT_CRXV_HE_RU1) & 0xff;
> + }
> +
> + if (status->bw >= RATE_INFO_BW_80) {
> + u32 ru_h, ru_l;
> +
> + he_mu->ru_ch1[1] = le32_get_bits(rxv[16],
> MT_CRXV_HE_RU2) & 0xff;
> +
> + ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L);
> + ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7;
> + he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4);
> + }
> +}
> +
> +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32
> *rxv,
> + u8 mode)
> +{
> + struct mt76_rx_status *status = (struct mt76_rx_status *)skb-
> >cb;
> + static const struct ieee80211_radiotap_he known = {
> + .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
> + HE_BITS(DATA1_DATA_DCM_KNOWN) |
> + HE_BITS(DATA1_STBC_KNOWN) |
> + HE_BITS(DATA1_CODING_KNOWN) |
> + HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
> + HE_BITS(DATA1_DOPPLER_KNOWN) |
> + HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
> + HE_BITS(DATA1_BSS_COLOR_KNOWN),
> + .data2 = HE_BITS(DATA2_GI_KNOWN) |
> + HE_BITS(DATA2_TXBF_KNOWN) |
> + HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
> + HE_BITS(DATA2_TXOP_KNOWN),
> + };
> + u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1;
> + struct ieee80211_radiotap_he *he;
> +
> + status->flag |= RX_FLAG_RADIOTAP_HE;
> +
> + he = skb_push(skb, sizeof(known));
> + memcpy(he, &known, sizeof(known));
> +
> + he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) |
> + HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]);
> + he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]);
> + he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) |
> + le16_encode_bits(ltf_size,
> + IEEE80211_RADIOTAP_HE_DATA5_LTF_SI
> ZE);
> + if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
> + he->data5 |= HE_BITS(DATA5_TXBF);
> + he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) |
> + HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]);
> +
> + switch (mode) {
> + case MT_PHY_TYPE_HE_SU:
> + he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
> + HE_BITS(DATA1_UL_DL_KNOWN) |
> + HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
> + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> +
> + he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG,
> rxv[8]) |
> + HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
> + break;
> + case MT_PHY_TYPE_HE_EXT_SU:
> + he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
> + HE_BITS(DATA1_UL_DL_KNOWN) |
> + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> +
> + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
> + break;
> + case MT_PHY_TYPE_HE_MU:
> + he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
> + HE_BITS(DATA1_UL_DL_KNOWN);
> +
> + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
> + he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]);
> +
> + mt76_connac3_mac_decode_he_radiotap_ru(status, he,
> rxv);
> + mt76_connac3_mac_decode_he_mu_radiotap(skb, rxv);
> + break;
> + case MT_PHY_TYPE_HE_TB:
> + he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
> + HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
> + HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
> + HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
> +
> + he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK,
> rxv[13]) |
> + HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK,
> rxv[13]) |
> + HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK,
> rxv[13]) |
> + HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK,
> rxv[13]);
> +
> + mt76_connac3_mac_decode_he_radiotap_ru(status, he,
> rxv);
> + break;
> + default:
> + break;
> + }
> +}
> +EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap);
> +
> +int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev,
> + struct mt76_rx_status *status,
> + struct ieee80211_supported_band
> *sband,
> + __le32 *rxv, u8 *mode)
> +{
> + u8 stbc, gi, bw, dcm, nss;
> + bool cck = false;
> + u32 v0, v2;
> + int i, idx;
> +
> + v0 = le32_to_cpu(rxv[0]);
> + v2 = le32_to_cpu(rxv[2]);
> +
> + idx = FIELD_GET(MT_PRXV_TX_RATE, v0);
> + i = idx;
> + nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1;
> +
> + stbc = FIELD_GET(MT_PRXV_HT_STBC, v2);
> + gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2);
> + *mode = FIELD_GET(MT_PRXV_TX_MODE, v2);
> + dcm = FIELD_GET(MT_PRXV_DCM, v2);
> + bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2);
> +
> + switch (*mode) {
> + case MT_PHY_TYPE_CCK:
> + cck = true;
> + fallthrough;
> + case MT_PHY_TYPE_OFDM:
> + i = mt76_get_rate(dev, sband, i, cck);
> + break;
> + case MT_PHY_TYPE_HT_GF:
> + case MT_PHY_TYPE_HT:
> + status->encoding = RX_ENC_HT;
> + if (gi)
> + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
> + if (i > 31)
> + return -EINVAL;
> + break;
> + case MT_PHY_TYPE_VHT:
> + status->nss = nss;
> + status->encoding = RX_ENC_VHT;
> + if (gi)
> + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
> + if (i > 11)
> + return -EINVAL;
> + break;
> + case MT_PHY_TYPE_HE_MU:
> + case MT_PHY_TYPE_HE_SU:
> + case MT_PHY_TYPE_HE_EXT_SU:
> + case MT_PHY_TYPE_HE_TB:
> + status->nss = nss;
> + status->encoding = RX_ENC_HE;
> + i &= GENMASK(3, 0);
> +
> + if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
> + status->he_gi = gi;
> +
> + status->he_dcm = dcm;
> + break;
> + case MT_PHY_TYPE_EHT_SU:
> + case MT_PHY_TYPE_EHT_TRIG:
> + case MT_PHY_TYPE_EHT_MU:
> + status->nss = nss;
> + status->encoding = RX_ENC_EHT;
> + i &= GENMASK(3, 0);
> +
> + if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
> + status->eht.gi = gi;
> + break;
> + default:
> + return -EINVAL;
> + }
> + status->rate_idx = i;
> +
> + switch (bw) {
> + case IEEE80211_STA_RX_BW_20:
> + break;
> + case IEEE80211_STA_RX_BW_40:
> + if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
> + (idx & MT_PRXV_TX_ER_SU_106T)) {
> + status->bw = RATE_INFO_BW_HE_RU;
> + status->he_ru =
> + NL80211_RATE_INFO_HE_RU_ALLOC_106;
> + } else {
> + status->bw = RATE_INFO_BW_40;
> + }
> + break;
> + case IEEE80211_STA_RX_BW_80:
> + status->bw = RATE_INFO_BW_80;
> + break;
> + case IEEE80211_STA_RX_BW_160:
> + status->bw = RATE_INFO_BW_160;
> + break;
> + case IEEE80211_STA_RX_BW_320:
> + status->bw = RATE_INFO_BW_320;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
> + if (*mode < MT_PHY_TYPE_HE_SU && gi)
> + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(mt76_connac3_mac_fill_rx_rate);
> +
> +static void
> +mt76_connac3_mac_write_txwi_8023(__le32 *txwi, struct sk_buff *skb,
> + struct mt76_wcid *wcid)
> +{
> + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
> + u8 fc_type, fc_stype;
> + u16 ethertype;
> + bool wmm = false;
> + u32 val;
> +
> + if (wcid->sta) {
> + struct ieee80211_sta *sta;
> +
> + sta = container_of((void *)wcid, struct ieee80211_sta,
> drv_priv);
> + wmm = sta->wme;
> + }
> +
> + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
> + FIELD_PREP(MT_TXD1_TID, tid);
> +
> + ethertype = get_unaligned_be16(&skb->data[12]);
> + if (ethertype >= ETH_P_802_3_MIN)
> + val |= MT_TXD1_ETH_802_3;
> +
> + txwi[1] |= cpu_to_le32(val);
> +
> + fc_type = IEEE80211_FTYPE_DATA >> 2;
> + fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0;
> +
> + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
> + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
> +
> + txwi[2] |= cpu_to_le32(val);
> +}
> +
> +static void
> +mt76_connac3_mac_write_txwi_80211(struct mt76_dev *dev, __le32
> *txwi,
> + struct sk_buff *skb,
> + struct ieee80211_key_conf *key)
> +{
> + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
> + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb-
> >data;
> + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> + bool multicast = is_multicast_ether_addr(hdr->addr1);
> + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
> + __le16 fc = hdr->frame_control;
> + u8 fc_type, fc_stype;
> + u32 val;
> +
> + if (ieee80211_is_action(fc) &&
> + mgmt->u.action.category == WLAN_CATEGORY_BACK &&
> + mgmt->u.action.u.addba_req.action_code ==
> WLAN_ACTION_ADDBA_REQ)
> + tid = MT_TX_ADDBA;
> + else if (ieee80211_is_mgmt(hdr->frame_control))
> + tid = MT_TX_NORMAL;
> +
> + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
> + FIELD_PREP(MT_TXD1_HDR_INFO,
> + ieee80211_get_hdrlen_from_skb(skb) / 2) |
> + FIELD_PREP(MT_TXD1_TID, tid);
> +
> + if (!ieee80211_is_data(fc) || multicast ||
> + info->flags & IEEE80211_TX_CTL_USE_MINRATE)
> + val |= MT_TXD1_FIXED_RATE;
> +
> + if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
> + key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
> + val |= MT_TXD1_BIP;
> + txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
> + }
> +
> + txwi[1] |= cpu_to_le32(val);
> +
> + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
> + fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
> +
> + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
> + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
> +
> + txwi[2] |= cpu_to_le32(val);
> +
> + txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast));
> + if (ieee80211_is_beacon(fc)) {
> + txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT);
> + txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
> + }
> +
> + if (info->flags & IEEE80211_TX_CTL_INJECTED) {
> + u16 seqno = le16_to_cpu(hdr->seq_ctrl);
> +
> + if (ieee80211_is_back_req(hdr->frame_control)) {
> + struct ieee80211_bar *bar;
> +
> + bar = (struct ieee80211_bar *)skb->data;
> + seqno = le16_to_cpu(bar->start_seq_num);
> + }
> +
> + val = MT_TXD3_SN_VALID |
> + FIELD_PREP(MT_TXD3_SEQ,
> IEEE80211_SEQ_TO_SN(seqno));
> + txwi[3] |= cpu_to_le32(val);
> + txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
> + }
> +}
> +
> +void mt76_connac3_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
> + struct sk_buff *skb, struct mt76_wcid
> *wcid,
> + struct ieee80211_key_conf *key, int
> pid,
> + enum mt76_txq_id qid, u32 changed)
> +{
> + u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE :
> MT_SDIO_TXD_SIZE;
> + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> + struct ieee80211_vif *vif = info->control.vif;
> + u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
> + u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
> + bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
> + struct mt76_vif *mvif;
> + u16 tx_count = 15;
> + bool beacon = !!(changed & (BSS_CHANGED_BEACON |
> + BSS_CHANGED_BEACON_ENABLED));
> + bool inband_disc = !!(changed &
> (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
> + BSS_CHANGED_FILS_DISCOVERY));
> +
> + mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL;
> + if (mvif) {
> + omac_idx = mvif->omac_idx;
> + wmm_idx = mvif->wmm_idx;
> + band_idx = mvif->band_idx;
> + }
> +
> + if (inband_disc) {
> + p_fmt = MT_TX_TYPE_FW;
> + q_idx = MT_LMAC_ALTX0;
> + } else if (beacon) {
> + p_fmt = MT_TX_TYPE_FW;
> + q_idx = MT_LMAC_BCN0;
> + } else if (qid >= MT_TXQ_PSD) {
> + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT :
> MT_TX_TYPE_SF;
> + q_idx = MT_LMAC_ALTX0;
> + } else {
> + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT :
> MT_TX_TYPE_SF;
> + q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS +
> + mt76_connac_lmac_mapping(skb_get_queue_mapping(
> skb));
> + }
> +
> + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
> + FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
> + FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
> + txwi[0] = cpu_to_le32(val);
> +
> + val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
> + FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
> +
> + if (band_idx)
> + val |= FIELD_PREP(MT_TXD1_TGID, band_idx);
> +
> + txwi[1] = cpu_to_le32(val);
> + txwi[2] = 0;
> +
> + val = MT_TXD3_SW_POWER_MGMT |
> + FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count);
> + if (key)
> + val |= MT_TXD3_PROTECT_FRAME;
> + if (info->flags & IEEE80211_TX_CTL_NO_ACK)
> + val |= MT_TXD3_NO_ACK;
> + if (wcid->amsdu)
> + val |= MT_TXD3_HW_AMSDU;
> +
> + txwi[3] = cpu_to_le32(val);
> + txwi[4] = 0;
> +
> + val = FIELD_PREP(MT_TXD5_PID, pid);
> + if (pid >= MT_PACKET_ID_FIRST)
> + val |= MT_TXD5_TX_STATUS_HOST;
> + txwi[5] = cpu_to_le32(val);
> +
> + val = MT_TXD6_DIS_MAT | MT_TXD6_DAS |
> + FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
> + txwi[6] = cpu_to_le32(val);
> + txwi[7] = 0;
> +
> + if (is_8023)
> + mt76_connac3_mac_write_txwi_8023(txwi, skb, wcid);
> + else
> + mt76_connac3_mac_write_txwi_80211(dev, txwi, skb, key);
> +
> + if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
> + struct ieee80211_hdr *hdr = (struct ieee80211_hdr
> *)skb->data;
> + bool mcast = ieee80211_is_data(hdr->frame_control) &&
> + is_multicast_ether_addr(hdr->addr1);
> + u8 idx = MT76_CONNAC3_BASIC_RATES_TBL;
> +
> + if (mvif) {
> + if (mcast && mvif->mcast_rates_idx)
> + idx = mvif->mcast_rates_idx;
> + else if (beacon && mvif->beacon_rates_idx)
> + idx = mvif->beacon_rates_idx;
> + else
> + idx = mvif->basic_rates_idx;
> + }
> +
> + txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE,
> idx));
> + txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
> + }
> +}
> +EXPORT_SYMBOL_GPL(mt76_connac3_mac_write_txwi);
> +
> +void mt76_connac3_txwi_free(struct mt76_dev *dev, struct
> mt76_txwi_cache *t,
> + struct ieee80211_sta *sta,
> + struct list_head *free_list)
> +{
> + __le32 *txwi;
> + u16 wcid_idx;
> +
> + mt76_connac_txp_skb_unmap(dev, t);
> + if (!t->skb)
> + goto out;
> +
> + txwi = (__le32 *)mt76_get_txwi_ptr(dev, t);
> + if (sta) {
> + struct mt76_wcid *wcid = (struct mt76_wcid *)sta-
> >drv_priv;
> +
> + wcid_idx = wcid->idx;
> + if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
> + mt76_connac3_tx_check_aggr(sta, txwi);
> + } else {
> + wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
> + }
> +
> + __mt76_tx_complete_skb(dev, wcid_idx, t->skb, free_list);
> +out:
> + t->skb = NULL;
> + mt76_put_txwi(dev, t);
> +}
> +EXPORT_SYMBOL_GPL(mt76_connac3_txwi_free);
> +
> +static bool
> +mt76_connac3_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid
> *wcid,
> + int pid, __le32 *txs_data)
> +{
> + struct mt76_sta_stats *stats = &wcid->stats;
> + struct ieee80211_supported_band *sband;
> + struct ieee80211_tx_info *info;
> + u32 txrate, txs, mode, stbc;
> + struct rate_info rate = {};
> + struct sk_buff_head list;
> + struct mt76_phy *mphy;
> + struct sk_buff *skb;
> + bool cck = false;
> +
> + mt76_tx_status_lock(dev, &list);
> + skb = mt76_tx_status_skb_get(dev, wcid, pid, &list);
> + if (!skb)
> + goto out_no_skb;
> +
> + txs = le32_to_cpu(txs_data[0]);
> +
> + info = IEEE80211_SKB_CB(skb);
> + if (!(txs & MT_TXS0_ACK_ERROR_MASK))
> + info->flags |= IEEE80211_TX_STAT_ACK;
> +
> + info->status.ampdu_len = 1;
> + info->status.ampdu_ack_len = !!(info->flags &
> + IEEE80211_TX_STAT_ACK);
> + info->status.rates[0].idx = -1;
> +
> + txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
> +
> + rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
> + rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
> + stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC);
> +
> + if (stbc && rate.nss > 1)
> + rate.nss >>= 1;
> +
> + if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
> + stats->tx_nss[rate.nss - 1]++;
> + if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
> + stats->tx_mcs[rate.mcs]++;
> +
> + mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
> + switch (mode) {
> + case MT_PHY_TYPE_CCK:
> + cck = true;
> + fallthrough;
> + case MT_PHY_TYPE_OFDM:
> + mphy = mt76_dev_phy(dev, wcid->phy_idx);
> +
> + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
> + sband = &mphy->sband_5g.sband;
> + else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
> + sband = &mphy->sband_6g.sband;
> + else
> + sband = &mphy->sband_2g.sband;
> +
> + rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs,
> cck);
> + rate.legacy = sband->bitrates[rate.mcs].bitrate;
> + break;
> + case MT_PHY_TYPE_HT:
> + case MT_PHY_TYPE_HT_GF:
> + if (rate.mcs > 31)
> + goto out;
> +
> + rate.flags = RATE_INFO_FLAGS_MCS;
> + if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
> + rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
> + break;
> + case MT_PHY_TYPE_VHT:
> + if (rate.mcs > 9)
> + goto out;
> +
> + rate.flags = RATE_INFO_FLAGS_VHT_MCS;
> + break;
> + case MT_PHY_TYPE_HE_SU:
> + case MT_PHY_TYPE_HE_EXT_SU:
> + case MT_PHY_TYPE_HE_TB:
> + case MT_PHY_TYPE_HE_MU:
> + if (rate.mcs > 11)
> + goto out;
> +
> + rate.he_gi = wcid->rate.he_gi;
> + rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
> + rate.flags = RATE_INFO_FLAGS_HE_MCS;
> + break;
> + case MT_PHY_TYPE_EHT_SU:
> + case MT_PHY_TYPE_EHT_TRIG:
> + case MT_PHY_TYPE_EHT_MU:
> + if (rate.mcs > 13)
> + goto out;
> +
> + rate.eht_gi = wcid->rate.eht_gi;
> + rate.flags = RATE_INFO_FLAGS_EHT_MCS;
> + break;
> + default:
> + goto out;
> + }
> +
> + stats->tx_mode[mode]++;
> +
> + switch (FIELD_GET(MT_TXS0_BW, txs)) {
> + case IEEE80211_STA_RX_BW_320:
> + rate.bw = RATE_INFO_BW_320;
> + stats->tx_bw[4]++;
> + break;
> + case IEEE80211_STA_RX_BW_160:
> + rate.bw = RATE_INFO_BW_160;
> + stats->tx_bw[3]++;
> + break;
> + case IEEE80211_STA_RX_BW_80:
> + rate.bw = RATE_INFO_BW_80;
> + stats->tx_bw[2]++;
> + break;
> + case IEEE80211_STA_RX_BW_40:
> + rate.bw = RATE_INFO_BW_40;
> + stats->tx_bw[1]++;
> + break;
> + default:
> + rate.bw = RATE_INFO_BW_20;
> + stats->tx_bw[0]++;
> + break;
> + }
> + wcid->rate = rate;
> +
> +out:
> + mt76_tx_status_skb_done(dev, skb, &list);
> +
> +out_no_skb:
> + mt76_tx_status_unlock(dev, &list);
> +
> + return !!skb;
> +}
> +
> +void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void *data,
> + u32 max_wtbl_size)
> +{
> + struct mt76_wcid *wcid;
> + __le32 *txs_data = data;
> + u16 wcidx;
> + u8 pid;
> +
> + if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
> + return;
> +
> + wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
> + pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
> +
> + if (pid < MT_PACKET_ID_FIRST)
> + return;
> +
> + if (wcidx >= max_wtbl_size)
> + return;
> +
> + rcu_read_lock();
> +
> + wcid = rcu_dereference(dev->wcid[wcidx]);
> + if (!wcid)
> + goto out;
> +
> + mt76_connac3_mac_add_txs_skb(dev, wcid, pid, txs_data);
> + if (!wcid->sta)
> + goto out;
> +
> + spin_lock_bh(&dev->sta_poll_lock);
> + if (list_empty(&wcid->poll_list))
> + list_add_tail(&wcid->poll_list, &dev->sta_poll_list);
> + spin_unlock_bh(&dev->sta_poll_lock);
> +
> +out:
> + rcu_read_unlock();
> +}
> +EXPORT_SYMBOL_GPL(mt76_connac3_mac_add_txs);
> +
> +void mt76_connac3_tx_token_put(struct mt76_dev *dev)
> +{
> + struct mt76_txwi_cache *txwi;
> + int id;
> +
> + spin_lock_bh(&dev->token_lock);
> + idr_for_each_entry(&dev->token, txwi, id) {
> + mt76_connac3_txwi_free(dev, txwi, NULL, NULL);
> + dev->token_count--;
> + }
> + spin_unlock_bh(&dev->token_lock);
> + idr_destroy(&dev->token);
> +}
> +EXPORT_SYMBOL_GPL(mt76_connac3_tx_token_put);
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> index 6663a0b46541..bcc1d976b2b0 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> @@ -4,6 +4,24 @@
> #ifndef __MT76_CONNAC3_MAC_H
> #define __MT76_CONNAC3_MAC_H
>
> +/* NOTE: used to map mt76_rates. idx may change if firmware expands
> table */
> +#define MT76_CONNAC3_BASIC_RATES_TBL 11
> +#define MT76_CONNAC3_BEACON_RATES_TBL 25
>
Different devices may have different defined value.
I'm thinking if it's too early to create this patch for just moving
mt7996 to connac3_lib?
Ryder
^ permalink raw reply [flat|nested] 27+ messages in thread* Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library
2023-06-09 16:15 ` Ryder Lee
@ 2023-06-09 16:34 ` lorenzo.bianconi
2023-06-09 16:38 ` Ryder Lee
0 siblings, 1 reply; 27+ messages in thread
From: lorenzo.bianconi @ 2023-06-09 16:34 UTC (permalink / raw)
To: Ryder Lee
Cc: nbd@nbd.name, lorenzo@kernel.org, linux-wireless@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 29436 bytes --]
On Jun 09, Ryder Lee wrote:
> On Fri, 2023-06-09 at 10:15 +0200, Lorenzo Bianconi wrote:
> >
> > External email : Please do not click links or open attachments until
> > you have verified the sender or the content.
> > Introduce connac3_mac in mt76_connac library to reuse mac code
> > shared
> > between WiFi7 chipsets.
> >
> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > ---
> > drivers/net/wireless/mediatek/mt76/Makefile | 2 +-
> > .../net/wireless/mediatek/mt76/mt76_connac.h | 19 +
> > .../wireless/mediatek/mt76/mt76_connac3_mac.c | 742
> > +++++++++++++++++
> > .../wireless/mediatek/mt76/mt76_connac3_mac.h | 18 +
> > .../net/wireless/mediatek/mt76/mt7996/init.c | 4 +-
> > .../net/wireless/mediatek/mt76/mt7996/mac.c | 761 +---------------
> > --
> > .../net/wireless/mediatek/mt76/mt7996/main.c | 8 +-
> > .../net/wireless/mediatek/mt76/mt7996/mcu.c | 9 +-
> > .../wireless/mediatek/mt76/mt7996/mt7996.h | 28 +-
> > 9 files changed, 807 insertions(+), 784 deletions(-)
> > create mode 100644
> > drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/Makefile
> > b/drivers/net/wireless/mediatek/mt76/Makefile
> > index 84c99b7e57f9..d8e8079c8b54 100644
> > --- a/drivers/net/wireless/mediatek/mt76/Makefile
> > +++ b/drivers/net/wireless/mediatek/mt76/Makefile
> > @@ -27,7 +27,7 @@ mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o
> > mt76x02_mcu.o \
> >
> > mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
> >
> > -mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
> > +mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
> > mt76_connac3_mac.o
> >
> > obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
> > obj-$(CONFIG_MT76x2_COMMON) += mt76x2/
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > index 68bdeada1421..20111678537b 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > @@ -415,4 +415,23 @@ void mt76_connac2_txwi_free(struct mt76_dev
> > *dev, struct mt76_txwi_cache *t,
> > struct list_head *free_list);
> > void mt76_connac2_tx_token_put(struct mt76_dev *dev);
> >
> > +/* connac3 */
> > +void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta, __le32
> > *txwi);
> > +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32
> > *rxv,
> > + u8 mode);
> > +int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev,
> > + struct mt76_rx_status *status,
> > + struct ieee80211_supported_band
> > *sband,
> > + __le32 *rxv, u8 *mode);
> > +void mt76_connac3_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
> > + struct sk_buff *skb, struct mt76_wcid
> > *wcid,
> > + struct ieee80211_key_conf *key, int
> > pid,
> > + enum mt76_txq_id qid, u32 changed);
> > +void mt76_connac3_txwi_free(struct mt76_dev *dev, struct
> > mt76_txwi_cache *t,
> > + struct ieee80211_sta *sta,
> > + struct list_head *free_list);
> > +void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void *data,
> > + u32 max_wtbl_size);
> > +void mt76_connac3_tx_token_put(struct mt76_dev *dev);
> > +
> > #endif /* __MT76_CONNAC_H */
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > new file mode 100644
> > index 000000000000..4b745bb74ca0
> > --- /dev/null
> > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > @@ -0,0 +1,742 @@
> > +// SPDX-License-Identifier: ISC
> > +/* Copyright (C) 2023 MediaTek Inc. */
> > +
> > +#include "mt76_connac.h"
> > +#include "mt76_connac3_mac.h"
> > +#include "dma.h"
> > +
> > +#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f)
> > +#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v,
> > MT_CRXV_HE_##m),\
> > + IEEE80211_RADIOTAP_HE_
> > ##f)
> > +
> > +void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta, __le32
> > *txwi)
> > +{
> > + struct mt76_wcid *wcid;
> > + u16 fc, tid;
> > + u32 val;
> > +
> > + if (!sta ||
> > + !(sta->deflink.ht_cap.ht_supported || sta-
> > >deflink.he_cap.has_he))
> > + return;
> > +
> > + tid = le32_get_bits(txwi[1], MT_TXD1_TID);
> > + if (tid >= 6) /* skip VO queue */
> > + return;
> > +
> > + val = le32_to_cpu(txwi[2]);
> > + fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
> > + FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
> > + if (unlikely(fc != (IEEE80211_FTYPE_DATA |
> > IEEE80211_STYPE_QOS_DATA)))
> > + return;
> > +
> > + wcid = (struct mt76_wcid *)sta->drv_priv;
> > + if (!test_and_set_bit(tid, &wcid->ampdu_state))
> > + ieee80211_start_tx_ba_session(sta, tid, 0);
> > +}
> > +EXPORT_SYMBOL_GPL(mt76_connac3_tx_check_aggr);
> > +
> > +static void
> > +mt76_connac3_mac_decode_he_radiotap_ru(struct mt76_rx_status
> > *status,
> > + struct ieee80211_radiotap_he
> > *he,
> > + __le32 *rxv)
> > +{
> > + u32 ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC), offs = 0;
> > +
> > + status->bw = RATE_INFO_BW_HE_RU;
> > +
> > + switch (ru) {
> > + case 0 ... 36:
> > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
> > + offs = ru;
> > + break;
> > + case 37 ... 52:
> > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
> > + offs = ru - 37;
> > + break;
> > + case 53 ... 60:
> > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
> > + offs = ru - 53;
> > + break;
> > + case 61 ... 64:
> > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
> > + offs = ru - 61;
> > + break;
> > + case 65 ... 66:
> > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
> > + offs = ru - 65;
> > + break;
> > + case 67:
> > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
> > + break;
> > + case 68:
> > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
> > + break;
> > + }
> > +
> > + he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > + he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
> > + le16_encode_bits(offs,
> > + IEEE80211_RADIOTAP_HE_DATA2_RU_OF
> > FSET);
> > +}
> > +
> > +#define MU_PREP(f, v) le16_encode_bits(v,
> > IEEE80211_RADIOTAP_HE_MU_##f)
> > +static void
> > +mt76_connac3_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32
> > *rxv)
> > +{
> > + struct mt76_rx_status *status = (struct mt76_rx_status *)skb-
> > >cb;
> > + static const struct ieee80211_radiotap_he_mu mu_known = {
> > + .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
> > + HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
> > + HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
> > + HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN),
> > + .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
> > + };
> > + struct ieee80211_radiotap_he_mu *he_mu;
> > +
> > + status->flag |= RX_FLAG_RADIOTAP_HE_MU;
> > +
> > + he_mu = skb_push(skb, sizeof(mu_known));
> > + memcpy(he_mu, &mu_known, sizeof(mu_known));
> > +
> > + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
> > + if (status->he_dcm)
> > + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status-
> > >he_dcm);
> > +
> > + he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
> > + MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
> > + le32_get_bits(rxv[4],
> > MT_CRXV_HE_NUM_USER));
> > +
> > + he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) &
> > 0xff;
> > +
> > + if (status->bw >= RATE_INFO_BW_40) {
> > + he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
> > + he_mu->ru_ch2[0] = le32_get_bits(rxv[16],
> > MT_CRXV_HE_RU1) & 0xff;
> > + }
> > +
> > + if (status->bw >= RATE_INFO_BW_80) {
> > + u32 ru_h, ru_l;
> > +
> > + he_mu->ru_ch1[1] = le32_get_bits(rxv[16],
> > MT_CRXV_HE_RU2) & 0xff;
> > +
> > + ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L);
> > + ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7;
> > + he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4);
> > + }
> > +}
> > +
> > +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32
> > *rxv,
> > + u8 mode)
> > +{
> > + struct mt76_rx_status *status = (struct mt76_rx_status *)skb-
> > >cb;
> > + static const struct ieee80211_radiotap_he known = {
> > + .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
> > + HE_BITS(DATA1_DATA_DCM_KNOWN) |
> > + HE_BITS(DATA1_STBC_KNOWN) |
> > + HE_BITS(DATA1_CODING_KNOWN) |
> > + HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
> > + HE_BITS(DATA1_DOPPLER_KNOWN) |
> > + HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
> > + HE_BITS(DATA1_BSS_COLOR_KNOWN),
> > + .data2 = HE_BITS(DATA2_GI_KNOWN) |
> > + HE_BITS(DATA2_TXBF_KNOWN) |
> > + HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
> > + HE_BITS(DATA2_TXOP_KNOWN),
> > + };
> > + u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1;
> > + struct ieee80211_radiotap_he *he;
> > +
> > + status->flag |= RX_FLAG_RADIOTAP_HE;
> > +
> > + he = skb_push(skb, sizeof(known));
> > + memcpy(he, &known, sizeof(known));
> > +
> > + he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) |
> > + HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]);
> > + he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]);
> > + he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) |
> > + le16_encode_bits(ltf_size,
> > + IEEE80211_RADIOTAP_HE_DATA5_LTF_SI
> > ZE);
> > + if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
> > + he->data5 |= HE_BITS(DATA5_TXBF);
> > + he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) |
> > + HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]);
> > +
> > + switch (mode) {
> > + case MT_PHY_TYPE_HE_SU:
> > + he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
> > + HE_BITS(DATA1_UL_DL_KNOWN) |
> > + HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
> > + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > +
> > + he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG,
> > rxv[8]) |
> > + HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
> > + break;
> > + case MT_PHY_TYPE_HE_EXT_SU:
> > + he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
> > + HE_BITS(DATA1_UL_DL_KNOWN) |
> > + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > +
> > + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
> > + break;
> > + case MT_PHY_TYPE_HE_MU:
> > + he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
> > + HE_BITS(DATA1_UL_DL_KNOWN);
> > +
> > + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
> > + he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]);
> > +
> > + mt76_connac3_mac_decode_he_radiotap_ru(status, he,
> > rxv);
> > + mt76_connac3_mac_decode_he_mu_radiotap(skb, rxv);
> > + break;
> > + case MT_PHY_TYPE_HE_TB:
> > + he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
> > + HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
> > + HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
> > + HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
> > +
> > + he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK,
> > rxv[13]) |
> > + HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK,
> > rxv[13]) |
> > + HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK,
> > rxv[13]) |
> > + HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK,
> > rxv[13]);
> > +
> > + mt76_connac3_mac_decode_he_radiotap_ru(status, he,
> > rxv);
> > + break;
> > + default:
> > + break;
> > + }
> > +}
> > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap);
> > +
> > +int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev,
> > + struct mt76_rx_status *status,
> > + struct ieee80211_supported_band
> > *sband,
> > + __le32 *rxv, u8 *mode)
> > +{
> > + u8 stbc, gi, bw, dcm, nss;
> > + bool cck = false;
> > + u32 v0, v2;
> > + int i, idx;
> > +
> > + v0 = le32_to_cpu(rxv[0]);
> > + v2 = le32_to_cpu(rxv[2]);
> > +
> > + idx = FIELD_GET(MT_PRXV_TX_RATE, v0);
> > + i = idx;
> > + nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1;
> > +
> > + stbc = FIELD_GET(MT_PRXV_HT_STBC, v2);
> > + gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2);
> > + *mode = FIELD_GET(MT_PRXV_TX_MODE, v2);
> > + dcm = FIELD_GET(MT_PRXV_DCM, v2);
> > + bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2);
> > +
> > + switch (*mode) {
> > + case MT_PHY_TYPE_CCK:
> > + cck = true;
> > + fallthrough;
> > + case MT_PHY_TYPE_OFDM:
> > + i = mt76_get_rate(dev, sband, i, cck);
> > + break;
> > + case MT_PHY_TYPE_HT_GF:
> > + case MT_PHY_TYPE_HT:
> > + status->encoding = RX_ENC_HT;
> > + if (gi)
> > + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
> > + if (i > 31)
> > + return -EINVAL;
> > + break;
> > + case MT_PHY_TYPE_VHT:
> > + status->nss = nss;
> > + status->encoding = RX_ENC_VHT;
> > + if (gi)
> > + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
> > + if (i > 11)
> > + return -EINVAL;
> > + break;
> > + case MT_PHY_TYPE_HE_MU:
> > + case MT_PHY_TYPE_HE_SU:
> > + case MT_PHY_TYPE_HE_EXT_SU:
> > + case MT_PHY_TYPE_HE_TB:
> > + status->nss = nss;
> > + status->encoding = RX_ENC_HE;
> > + i &= GENMASK(3, 0);
> > +
> > + if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
> > + status->he_gi = gi;
> > +
> > + status->he_dcm = dcm;
> > + break;
> > + case MT_PHY_TYPE_EHT_SU:
> > + case MT_PHY_TYPE_EHT_TRIG:
> > + case MT_PHY_TYPE_EHT_MU:
> > + status->nss = nss;
> > + status->encoding = RX_ENC_EHT;
> > + i &= GENMASK(3, 0);
> > +
> > + if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
> > + status->eht.gi = gi;
> > + break;
> > + default:
> > + return -EINVAL;
> > + }
> > + status->rate_idx = i;
> > +
> > + switch (bw) {
> > + case IEEE80211_STA_RX_BW_20:
> > + break;
> > + case IEEE80211_STA_RX_BW_40:
> > + if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
> > + (idx & MT_PRXV_TX_ER_SU_106T)) {
> > + status->bw = RATE_INFO_BW_HE_RU;
> > + status->he_ru =
> > + NL80211_RATE_INFO_HE_RU_ALLOC_106;
> > + } else {
> > + status->bw = RATE_INFO_BW_40;
> > + }
> > + break;
> > + case IEEE80211_STA_RX_BW_80:
> > + status->bw = RATE_INFO_BW_80;
> > + break;
> > + case IEEE80211_STA_RX_BW_160:
> > + status->bw = RATE_INFO_BW_160;
> > + break;
> > + case IEEE80211_STA_RX_BW_320:
> > + status->bw = RATE_INFO_BW_320;
> > + break;
> > + default:
> > + return -EINVAL;
> > + }
> > +
> > + status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
> > + if (*mode < MT_PHY_TYPE_HE_SU && gi)
> > + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
> > +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_fill_rx_rate);
> > +
> > +static void
> > +mt76_connac3_mac_write_txwi_8023(__le32 *txwi, struct sk_buff *skb,
> > + struct mt76_wcid *wcid)
> > +{
> > + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
> > + u8 fc_type, fc_stype;
> > + u16 ethertype;
> > + bool wmm = false;
> > + u32 val;
> > +
> > + if (wcid->sta) {
> > + struct ieee80211_sta *sta;
> > +
> > + sta = container_of((void *)wcid, struct ieee80211_sta,
> > drv_priv);
> > + wmm = sta->wme;
> > + }
> > +
> > + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
> > + FIELD_PREP(MT_TXD1_TID, tid);
> > +
> > + ethertype = get_unaligned_be16(&skb->data[12]);
> > + if (ethertype >= ETH_P_802_3_MIN)
> > + val |= MT_TXD1_ETH_802_3;
> > +
> > + txwi[1] |= cpu_to_le32(val);
> > +
> > + fc_type = IEEE80211_FTYPE_DATA >> 2;
> > + fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0;
> > +
> > + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
> > + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
> > +
> > + txwi[2] |= cpu_to_le32(val);
> > +}
> > +
> > +static void
> > +mt76_connac3_mac_write_txwi_80211(struct mt76_dev *dev, __le32
> > *txwi,
> > + struct sk_buff *skb,
> > + struct ieee80211_key_conf *key)
> > +{
> > + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
> > + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb-
> > >data;
> > + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> > + bool multicast = is_multicast_ether_addr(hdr->addr1);
> > + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
> > + __le16 fc = hdr->frame_control;
> > + u8 fc_type, fc_stype;
> > + u32 val;
> > +
> > + if (ieee80211_is_action(fc) &&
> > + mgmt->u.action.category == WLAN_CATEGORY_BACK &&
> > + mgmt->u.action.u.addba_req.action_code ==
> > WLAN_ACTION_ADDBA_REQ)
> > + tid = MT_TX_ADDBA;
> > + else if (ieee80211_is_mgmt(hdr->frame_control))
> > + tid = MT_TX_NORMAL;
> > +
> > + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
> > + FIELD_PREP(MT_TXD1_HDR_INFO,
> > + ieee80211_get_hdrlen_from_skb(skb) / 2) |
> > + FIELD_PREP(MT_TXD1_TID, tid);
> > +
> > + if (!ieee80211_is_data(fc) || multicast ||
> > + info->flags & IEEE80211_TX_CTL_USE_MINRATE)
> > + val |= MT_TXD1_FIXED_RATE;
> > +
> > + if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
> > + key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
> > + val |= MT_TXD1_BIP;
> > + txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
> > + }
> > +
> > + txwi[1] |= cpu_to_le32(val);
> > +
> > + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
> > + fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
> > +
> > + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
> > + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
> > +
> > + txwi[2] |= cpu_to_le32(val);
> > +
> > + txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast));
> > + if (ieee80211_is_beacon(fc)) {
> > + txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT);
> > + txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
> > + }
> > +
> > + if (info->flags & IEEE80211_TX_CTL_INJECTED) {
> > + u16 seqno = le16_to_cpu(hdr->seq_ctrl);
> > +
> > + if (ieee80211_is_back_req(hdr->frame_control)) {
> > + struct ieee80211_bar *bar;
> > +
> > + bar = (struct ieee80211_bar *)skb->data;
> > + seqno = le16_to_cpu(bar->start_seq_num);
> > + }
> > +
> > + val = MT_TXD3_SN_VALID |
> > + FIELD_PREP(MT_TXD3_SEQ,
> > IEEE80211_SEQ_TO_SN(seqno));
> > + txwi[3] |= cpu_to_le32(val);
> > + txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
> > + }
> > +}
> > +
> > +void mt76_connac3_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
> > + struct sk_buff *skb, struct mt76_wcid
> > *wcid,
> > + struct ieee80211_key_conf *key, int
> > pid,
> > + enum mt76_txq_id qid, u32 changed)
> > +{
> > + u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE :
> > MT_SDIO_TXD_SIZE;
> > + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> > + struct ieee80211_vif *vif = info->control.vif;
> > + u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
> > + u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
> > + bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
> > + struct mt76_vif *mvif;
> > + u16 tx_count = 15;
> > + bool beacon = !!(changed & (BSS_CHANGED_BEACON |
> > + BSS_CHANGED_BEACON_ENABLED));
> > + bool inband_disc = !!(changed &
> > (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
> > + BSS_CHANGED_FILS_DISCOVERY));
> > +
> > + mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL;
> > + if (mvif) {
> > + omac_idx = mvif->omac_idx;
> > + wmm_idx = mvif->wmm_idx;
> > + band_idx = mvif->band_idx;
> > + }
> > +
> > + if (inband_disc) {
> > + p_fmt = MT_TX_TYPE_FW;
> > + q_idx = MT_LMAC_ALTX0;
> > + } else if (beacon) {
> > + p_fmt = MT_TX_TYPE_FW;
> > + q_idx = MT_LMAC_BCN0;
> > + } else if (qid >= MT_TXQ_PSD) {
> > + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT :
> > MT_TX_TYPE_SF;
> > + q_idx = MT_LMAC_ALTX0;
> > + } else {
> > + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT :
> > MT_TX_TYPE_SF;
> > + q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS +
> > + mt76_connac_lmac_mapping(skb_get_queue_mapping(
> > skb));
> > + }
> > +
> > + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
> > + FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
> > + FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
> > + txwi[0] = cpu_to_le32(val);
> > +
> > + val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
> > + FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
> > +
> > + if (band_idx)
> > + val |= FIELD_PREP(MT_TXD1_TGID, band_idx);
> > +
> > + txwi[1] = cpu_to_le32(val);
> > + txwi[2] = 0;
> > +
> > + val = MT_TXD3_SW_POWER_MGMT |
> > + FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count);
> > + if (key)
> > + val |= MT_TXD3_PROTECT_FRAME;
> > + if (info->flags & IEEE80211_TX_CTL_NO_ACK)
> > + val |= MT_TXD3_NO_ACK;
> > + if (wcid->amsdu)
> > + val |= MT_TXD3_HW_AMSDU;
> > +
> > + txwi[3] = cpu_to_le32(val);
> > + txwi[4] = 0;
> > +
> > + val = FIELD_PREP(MT_TXD5_PID, pid);
> > + if (pid >= MT_PACKET_ID_FIRST)
> > + val |= MT_TXD5_TX_STATUS_HOST;
> > + txwi[5] = cpu_to_le32(val);
> > +
> > + val = MT_TXD6_DIS_MAT | MT_TXD6_DAS |
> > + FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
> > + txwi[6] = cpu_to_le32(val);
> > + txwi[7] = 0;
> > +
> > + if (is_8023)
> > + mt76_connac3_mac_write_txwi_8023(txwi, skb, wcid);
> > + else
> > + mt76_connac3_mac_write_txwi_80211(dev, txwi, skb, key);
> > +
> > + if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
> > + struct ieee80211_hdr *hdr = (struct ieee80211_hdr
> > *)skb->data;
> > + bool mcast = ieee80211_is_data(hdr->frame_control) &&
> > + is_multicast_ether_addr(hdr->addr1);
> > + u8 idx = MT76_CONNAC3_BASIC_RATES_TBL;
> > +
> > + if (mvif) {
> > + if (mcast && mvif->mcast_rates_idx)
> > + idx = mvif->mcast_rates_idx;
> > + else if (beacon && mvif->beacon_rates_idx)
> > + idx = mvif->beacon_rates_idx;
> > + else
> > + idx = mvif->basic_rates_idx;
> > + }
> > +
> > + txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE,
> > idx));
> > + txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
> > + }
> > +}
> > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_write_txwi);
> > +
> > +void mt76_connac3_txwi_free(struct mt76_dev *dev, struct
> > mt76_txwi_cache *t,
> > + struct ieee80211_sta *sta,
> > + struct list_head *free_list)
> > +{
> > + __le32 *txwi;
> > + u16 wcid_idx;
> > +
> > + mt76_connac_txp_skb_unmap(dev, t);
> > + if (!t->skb)
> > + goto out;
> > +
> > + txwi = (__le32 *)mt76_get_txwi_ptr(dev, t);
> > + if (sta) {
> > + struct mt76_wcid *wcid = (struct mt76_wcid *)sta-
> > >drv_priv;
> > +
> > + wcid_idx = wcid->idx;
> > + if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
> > + mt76_connac3_tx_check_aggr(sta, txwi);
> > + } else {
> > + wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
> > + }
> > +
> > + __mt76_tx_complete_skb(dev, wcid_idx, t->skb, free_list);
> > +out:
> > + t->skb = NULL;
> > + mt76_put_txwi(dev, t);
> > +}
> > +EXPORT_SYMBOL_GPL(mt76_connac3_txwi_free);
> > +
> > +static bool
> > +mt76_connac3_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid
> > *wcid,
> > + int pid, __le32 *txs_data)
> > +{
> > + struct mt76_sta_stats *stats = &wcid->stats;
> > + struct ieee80211_supported_band *sband;
> > + struct ieee80211_tx_info *info;
> > + u32 txrate, txs, mode, stbc;
> > + struct rate_info rate = {};
> > + struct sk_buff_head list;
> > + struct mt76_phy *mphy;
> > + struct sk_buff *skb;
> > + bool cck = false;
> > +
> > + mt76_tx_status_lock(dev, &list);
> > + skb = mt76_tx_status_skb_get(dev, wcid, pid, &list);
> > + if (!skb)
> > + goto out_no_skb;
> > +
> > + txs = le32_to_cpu(txs_data[0]);
> > +
> > + info = IEEE80211_SKB_CB(skb);
> > + if (!(txs & MT_TXS0_ACK_ERROR_MASK))
> > + info->flags |= IEEE80211_TX_STAT_ACK;
> > +
> > + info->status.ampdu_len = 1;
> > + info->status.ampdu_ack_len = !!(info->flags &
> > + IEEE80211_TX_STAT_ACK);
> > + info->status.rates[0].idx = -1;
> > +
> > + txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
> > +
> > + rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
> > + rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
> > + stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC);
> > +
> > + if (stbc && rate.nss > 1)
> > + rate.nss >>= 1;
> > +
> > + if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
> > + stats->tx_nss[rate.nss - 1]++;
> > + if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
> > + stats->tx_mcs[rate.mcs]++;
> > +
> > + mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
> > + switch (mode) {
> > + case MT_PHY_TYPE_CCK:
> > + cck = true;
> > + fallthrough;
> > + case MT_PHY_TYPE_OFDM:
> > + mphy = mt76_dev_phy(dev, wcid->phy_idx);
> > +
> > + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
> > + sband = &mphy->sband_5g.sband;
> > + else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
> > + sband = &mphy->sband_6g.sband;
> > + else
> > + sband = &mphy->sband_2g.sband;
> > +
> > + rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs,
> > cck);
> > + rate.legacy = sband->bitrates[rate.mcs].bitrate;
> > + break;
> > + case MT_PHY_TYPE_HT:
> > + case MT_PHY_TYPE_HT_GF:
> > + if (rate.mcs > 31)
> > + goto out;
> > +
> > + rate.flags = RATE_INFO_FLAGS_MCS;
> > + if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
> > + rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
> > + break;
> > + case MT_PHY_TYPE_VHT:
> > + if (rate.mcs > 9)
> > + goto out;
> > +
> > + rate.flags = RATE_INFO_FLAGS_VHT_MCS;
> > + break;
> > + case MT_PHY_TYPE_HE_SU:
> > + case MT_PHY_TYPE_HE_EXT_SU:
> > + case MT_PHY_TYPE_HE_TB:
> > + case MT_PHY_TYPE_HE_MU:
> > + if (rate.mcs > 11)
> > + goto out;
> > +
> > + rate.he_gi = wcid->rate.he_gi;
> > + rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
> > + rate.flags = RATE_INFO_FLAGS_HE_MCS;
> > + break;
> > + case MT_PHY_TYPE_EHT_SU:
> > + case MT_PHY_TYPE_EHT_TRIG:
> > + case MT_PHY_TYPE_EHT_MU:
> > + if (rate.mcs > 13)
> > + goto out;
> > +
> > + rate.eht_gi = wcid->rate.eht_gi;
> > + rate.flags = RATE_INFO_FLAGS_EHT_MCS;
> > + break;
> > + default:
> > + goto out;
> > + }
> > +
> > + stats->tx_mode[mode]++;
> > +
> > + switch (FIELD_GET(MT_TXS0_BW, txs)) {
> > + case IEEE80211_STA_RX_BW_320:
> > + rate.bw = RATE_INFO_BW_320;
> > + stats->tx_bw[4]++;
> > + break;
> > + case IEEE80211_STA_RX_BW_160:
> > + rate.bw = RATE_INFO_BW_160;
> > + stats->tx_bw[3]++;
> > + break;
> > + case IEEE80211_STA_RX_BW_80:
> > + rate.bw = RATE_INFO_BW_80;
> > + stats->tx_bw[2]++;
> > + break;
> > + case IEEE80211_STA_RX_BW_40:
> > + rate.bw = RATE_INFO_BW_40;
> > + stats->tx_bw[1]++;
> > + break;
> > + default:
> > + rate.bw = RATE_INFO_BW_20;
> > + stats->tx_bw[0]++;
> > + break;
> > + }
> > + wcid->rate = rate;
> > +
> > +out:
> > + mt76_tx_status_skb_done(dev, skb, &list);
> > +
> > +out_no_skb:
> > + mt76_tx_status_unlock(dev, &list);
> > +
> > + return !!skb;
> > +}
> > +
> > +void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void *data,
> > + u32 max_wtbl_size)
> > +{
> > + struct mt76_wcid *wcid;
> > + __le32 *txs_data = data;
> > + u16 wcidx;
> > + u8 pid;
> > +
> > + if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
> > + return;
> > +
> > + wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
> > + pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
> > +
> > + if (pid < MT_PACKET_ID_FIRST)
> > + return;
> > +
> > + if (wcidx >= max_wtbl_size)
> > + return;
> > +
> > + rcu_read_lock();
> > +
> > + wcid = rcu_dereference(dev->wcid[wcidx]);
> > + if (!wcid)
> > + goto out;
> > +
> > + mt76_connac3_mac_add_txs_skb(dev, wcid, pid, txs_data);
> > + if (!wcid->sta)
> > + goto out;
> > +
> > + spin_lock_bh(&dev->sta_poll_lock);
> > + if (list_empty(&wcid->poll_list))
> > + list_add_tail(&wcid->poll_list, &dev->sta_poll_list);
> > + spin_unlock_bh(&dev->sta_poll_lock);
> > +
> > +out:
> > + rcu_read_unlock();
> > +}
> > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_add_txs);
> > +
> > +void mt76_connac3_tx_token_put(struct mt76_dev *dev)
> > +{
> > + struct mt76_txwi_cache *txwi;
> > + int id;
> > +
> > + spin_lock_bh(&dev->token_lock);
> > + idr_for_each_entry(&dev->token, txwi, id) {
> > + mt76_connac3_txwi_free(dev, txwi, NULL, NULL);
> > + dev->token_count--;
> > + }
> > + spin_unlock_bh(&dev->token_lock);
> > + idr_destroy(&dev->token);
> > +}
> > +EXPORT_SYMBOL_GPL(mt76_connac3_tx_token_put);
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > index 6663a0b46541..bcc1d976b2b0 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > @@ -4,6 +4,24 @@
> > #ifndef __MT76_CONNAC3_MAC_H
> > #define __MT76_CONNAC3_MAC_H
> >
> > +/* NOTE: used to map mt76_rates. idx may change if firmware expands
> > table */
> > +#define MT76_CONNAC3_BASIC_RATES_TBL 11
> > +#define MT76_CONNAC3_BEACON_RATES_TBL 25
> >
>
> Different devices may have different defined value.
The other WiFi7 device I am working on relies on the values I moved in
mt76_connac3_mac.h (in common with mt7996). Moreover you can still
have per-device values in mt7996/mac.h (I have not removed it).
>
> I'm thinking if it's too early to create this patch for just moving
> mt7996 to connac3_lib?
The code I moved is used by the other device as well. This series is a
preliminary series to support it.
Regards,
Lorenzo
>
> Ryder
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread* Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library
2023-06-09 16:34 ` lorenzo.bianconi
@ 2023-06-09 16:38 ` Ryder Lee
2023-06-09 16:45 ` lorenzo
0 siblings, 1 reply; 27+ messages in thread
From: Ryder Lee @ 2023-06-09 16:38 UTC (permalink / raw)
To: lorenzo.bianconi@redhat.com
Cc: linux-wireless@vger.kernel.org, nbd@nbd.name, lorenzo@kernel.org
On Fri, 2023-06-09 at 18:34 +0200, lorenzo.bianconi@redhat.com wrote:
> On Jun 09, Ryder Lee wrote:
> > On Fri, 2023-06-09 at 10:15 +0200, Lorenzo Bianconi wrote:
> > >
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > > Introduce connac3_mac in mt76_connac library to reuse mac code
> > > shared
> > > between WiFi7 chipsets.
> > >
> > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > ---
> > > drivers/net/wireless/mediatek/mt76/Makefile | 2 +-
> > > .../net/wireless/mediatek/mt76/mt76_connac.h | 19 +
> > > .../wireless/mediatek/mt76/mt76_connac3_mac.c | 742
> > > +++++++++++++++++
> > > .../wireless/mediatek/mt76/mt76_connac3_mac.h | 18 +
> > > .../net/wireless/mediatek/mt76/mt7996/init.c | 4 +-
> > > .../net/wireless/mediatek/mt76/mt7996/mac.c | 761 +-----------
> > > ----
> > > --
> > > .../net/wireless/mediatek/mt76/mt7996/main.c | 8 +-
> > > .../net/wireless/mediatek/mt76/mt7996/mcu.c | 9 +-
> > > .../wireless/mediatek/mt76/mt7996/mt7996.h | 28 +-
> > > 9 files changed, 807 insertions(+), 784 deletions(-)
> > > create mode 100644
> > > drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > >
> > > diff --git a/drivers/net/wireless/mediatek/mt76/Makefile
> > > b/drivers/net/wireless/mediatek/mt76/Makefile
> > > index 84c99b7e57f9..d8e8079c8b54 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/Makefile
> > > +++ b/drivers/net/wireless/mediatek/mt76/Makefile
> > > @@ -27,7 +27,7 @@ mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o
> > > mt76x02_mcu.o \
> > >
> > > mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
> > >
> > > -mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
> > > +mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
> > > mt76_connac3_mac.o
> > >
> > > obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
> > > obj-$(CONFIG_MT76x2_COMMON) += mt76x2/
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > index 68bdeada1421..20111678537b 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > @@ -415,4 +415,23 @@ void mt76_connac2_txwi_free(struct mt76_dev
> > > *dev, struct mt76_txwi_cache *t,
> > > struct list_head *free_list);
> > > void mt76_connac2_tx_token_put(struct mt76_dev *dev);
> > >
> > > +/* connac3 */
> > > +void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta,
> > > __le32
> > > *txwi);
> > > +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb,
> > > __le32
> > > *rxv,
> > > + u8 mode);
> > > +int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev,
> > > + struct mt76_rx_status *status,
> > > + struct ieee80211_supported_band
> > > *sband,
> > > + __le32 *rxv, u8 *mode);
> > > +void mt76_connac3_mac_write_txwi(struct mt76_dev *dev, __le32
> > > *txwi,
> > > + struct sk_buff *skb, struct mt76_wcid
> > > *wcid,
> > > + struct ieee80211_key_conf *key, int
> > > pid,
> > > + enum mt76_txq_id qid, u32 changed);
> > > +void mt76_connac3_txwi_free(struct mt76_dev *dev, struct
> > > mt76_txwi_cache *t,
> > > + struct ieee80211_sta *sta,
> > > + struct list_head *free_list);
> > > +void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void *data,
> > > + u32 max_wtbl_size);
> > > +void mt76_connac3_tx_token_put(struct mt76_dev *dev);
> > > +
> > > #endif /* __MT76_CONNAC_H */
> > > diff --git
> > > a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > new file mode 100644
> > > index 000000000000..4b745bb74ca0
> > > --- /dev/null
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > @@ -0,0 +1,742 @@
> > > +// SPDX-License-Identifier: ISC
> > > +/* Copyright (C) 2023 MediaTek Inc. */
> > > +
> > > +#include "mt76_connac.h"
> > > +#include "mt76_connac3_mac.h"
> > > +#include "dma.h"
> > > +
> > > +#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_
> > > HE_##f)
> > > +#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v,
> > > MT_CRXV_HE_##m),\
> > > + IEEE80211_RADIOTAP_HE_
> > > ##f)
> > > +
> > > +void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta,
> > > __le32
> > > *txwi)
> > > +{
> > > + struct mt76_wcid *wcid;
> > > + u16 fc, tid;
> > > + u32 val;
> > > +
> > > + if (!sta ||
> > > + !(sta->deflink.ht_cap.ht_supported || sta-
> > > > deflink.he_cap.has_he))
> > >
> > > + return;
> > > +
> > > + tid = le32_get_bits(txwi[1], MT_TXD1_TID);
> > > + if (tid >= 6) /* skip VO queue */
> > > + return;
> > > +
> > > + val = le32_to_cpu(txwi[2]);
> > > + fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
> > > + FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
> > > + if (unlikely(fc != (IEEE80211_FTYPE_DATA |
> > > IEEE80211_STYPE_QOS_DATA)))
> > > + return;
> > > +
> > > + wcid = (struct mt76_wcid *)sta->drv_priv;
> > > + if (!test_and_set_bit(tid, &wcid->ampdu_state))
> > > + ieee80211_start_tx_ba_session(sta, tid, 0);
> > > +}
> > > +EXPORT_SYMBOL_GPL(mt76_connac3_tx_check_aggr);
> > > +
> > > +static void
> > > +mt76_connac3_mac_decode_he_radiotap_ru(struct mt76_rx_status
> > > *status,
> > > + struct ieee80211_radiotap_he
> > > *he,
> > > + __le32 *rxv)
> > > +{
> > > + u32 ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC), offs = 0;
> > > +
> > > + status->bw = RATE_INFO_BW_HE_RU;
> > > +
> > > + switch (ru) {
> > > + case 0 ... 36:
> > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
> > > + offs = ru;
> > > + break;
> > > + case 37 ... 52:
> > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
> > > + offs = ru - 37;
> > > + break;
> > > + case 53 ... 60:
> > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
> > > + offs = ru - 53;
> > > + break;
> > > + case 61 ... 64:
> > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
> > > + offs = ru - 61;
> > > + break;
> > > + case 65 ... 66:
> > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
> > > + offs = ru - 65;
> > > + break;
> > > + case 67:
> > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
> > > + break;
> > > + case 68:
> > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
> > > + break;
> > > + }
> > > +
> > > + he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > > + he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
> > > + le16_encode_bits(offs,
> > > + IEEE80211_RADIOTAP_HE_DATA2_RU_OF
> > > FSET);
> > > +}
> > > +
> > > +#define MU_PREP(f, v) le16_encode_bits(v,
> > > IEEE80211_RADIOTAP_HE_MU_##f)
> > > +static void
> > > +mt76_connac3_mac_decode_he_mu_radiotap(struct sk_buff *skb,
> > > __le32
> > > *rxv)
> > > +{
> > > + struct mt76_rx_status *status = (struct mt76_rx_status *)skb-
> > > > cb;
> > >
> > > + static const struct ieee80211_radiotap_he_mu mu_known = {
> > > + .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
> > > + HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
> > > + HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
> > > + HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN),
> > > + .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
> > > + };
> > > + struct ieee80211_radiotap_he_mu *he_mu;
> > > +
> > > + status->flag |= RX_FLAG_RADIOTAP_HE_MU;
> > > +
> > > + he_mu = skb_push(skb, sizeof(mu_known));
> > > + memcpy(he_mu, &mu_known, sizeof(mu_known));
> > > +
> > > + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
> > > + if (status->he_dcm)
> > > + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status-
> > > > he_dcm);
> > >
> > > +
> > > + he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
> > > + MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
> > > + le32_get_bits(rxv[4],
> > > MT_CRXV_HE_NUM_USER));
> > > +
> > > + he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) &
> > > 0xff;
> > > +
> > > + if (status->bw >= RATE_INFO_BW_40) {
> > > + he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
> > > + he_mu->ru_ch2[0] = le32_get_bits(rxv[16],
> > > MT_CRXV_HE_RU1) & 0xff;
> > > + }
> > > +
> > > + if (status->bw >= RATE_INFO_BW_80) {
> > > + u32 ru_h, ru_l;
> > > +
> > > + he_mu->ru_ch1[1] = le32_get_bits(rxv[16],
> > > MT_CRXV_HE_RU2) & 0xff;
> > > +
> > > + ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L);
> > > + ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7;
> > > + he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4);
> > > + }
> > > +}
> > > +
> > > +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb,
> > > __le32
> > > *rxv,
> > > + u8 mode)
> > > +{
> > > + struct mt76_rx_status *status = (struct mt76_rx_status *)skb-
> > > > cb;
> > >
> > > + static const struct ieee80211_radiotap_he known = {
> > > + .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
> > > + HE_BITS(DATA1_DATA_DCM_KNOWN) |
> > > + HE_BITS(DATA1_STBC_KNOWN) |
> > > + HE_BITS(DATA1_CODING_KNOWN) |
> > > + HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
> > > + HE_BITS(DATA1_DOPPLER_KNOWN) |
> > > + HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
> > > + HE_BITS(DATA1_BSS_COLOR_KNOWN),
> > > + .data2 = HE_BITS(DATA2_GI_KNOWN) |
> > > + HE_BITS(DATA2_TXBF_KNOWN) |
> > > + HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
> > > + HE_BITS(DATA2_TXOP_KNOWN),
> > > + };
> > > + u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1;
> > > + struct ieee80211_radiotap_he *he;
> > > +
> > > + status->flag |= RX_FLAG_RADIOTAP_HE;
> > > +
> > > + he = skb_push(skb, sizeof(known));
> > > + memcpy(he, &known, sizeof(known));
> > > +
> > > + he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) |
> > > + HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]);
> > > + he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]);
> > > + he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) |
> > > + le16_encode_bits(ltf_size,
> > > + IEEE80211_RADIOTAP_HE_DATA5_LTF_SI
> > > ZE);
> > > + if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
> > > + he->data5 |= HE_BITS(DATA5_TXBF);
> > > + he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) |
> > > + HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]);
> > > +
> > > + switch (mode) {
> > > + case MT_PHY_TYPE_HE_SU:
> > > + he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
> > > + HE_BITS(DATA1_UL_DL_KNOWN) |
> > > + HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
> > > + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > > +
> > > + he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG,
> > > rxv[8]) |
> > > + HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
> > > + break;
> > > + case MT_PHY_TYPE_HE_EXT_SU:
> > > + he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
> > > + HE_BITS(DATA1_UL_DL_KNOWN) |
> > > + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > > +
> > > + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
> > > + break;
> > > + case MT_PHY_TYPE_HE_MU:
> > > + he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
> > > + HE_BITS(DATA1_UL_DL_KNOWN);
> > > +
> > > + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
> > > + he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]);
> > > +
> > > + mt76_connac3_mac_decode_he_radiotap_ru(status, he,
> > > rxv);
> > > + mt76_connac3_mac_decode_he_mu_radiotap(skb, rxv);
> > > + break;
> > > + case MT_PHY_TYPE_HE_TB:
> > > + he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
> > > + HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
> > > + HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
> > > + HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
> > > +
> > > + he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK,
> > > rxv[13]) |
> > > + HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK,
> > > rxv[13]) |
> > > + HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK,
> > > rxv[13]) |
> > > + HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK,
> > > rxv[13]);
> > > +
> > > + mt76_connac3_mac_decode_he_radiotap_ru(status, he,
> > > rxv);
> > > + break;
> > > + default:
> > > + break;
> > > + }
> > > +}
> > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap);
> > > +
> > > +int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev,
> > > + struct mt76_rx_status *status,
> > > + struct ieee80211_supported_band
> > > *sband,
> > > + __le32 *rxv, u8 *mode)
> > > +{
> > > + u8 stbc, gi, bw, dcm, nss;
> > > + bool cck = false;
> > > + u32 v0, v2;
> > > + int i, idx;
> > > +
> > > + v0 = le32_to_cpu(rxv[0]);
> > > + v2 = le32_to_cpu(rxv[2]);
> > > +
> > > + idx = FIELD_GET(MT_PRXV_TX_RATE, v0);
> > > + i = idx;
> > > + nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1;
> > > +
> > > + stbc = FIELD_GET(MT_PRXV_HT_STBC, v2);
> > > + gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2);
> > > + *mode = FIELD_GET(MT_PRXV_TX_MODE, v2);
> > > + dcm = FIELD_GET(MT_PRXV_DCM, v2);
> > > + bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2);
> > > +
> > > + switch (*mode) {
> > > + case MT_PHY_TYPE_CCK:
> > > + cck = true;
> > > + fallthrough;
> > > + case MT_PHY_TYPE_OFDM:
> > > + i = mt76_get_rate(dev, sband, i, cck);
> > > + break;
> > > + case MT_PHY_TYPE_HT_GF:
> > > + case MT_PHY_TYPE_HT:
> > > + status->encoding = RX_ENC_HT;
> > > + if (gi)
> > > + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
> > > + if (i > 31)
> > > + return -EINVAL;
> > > + break;
> > > + case MT_PHY_TYPE_VHT:
> > > + status->nss = nss;
> > > + status->encoding = RX_ENC_VHT;
> > > + if (gi)
> > > + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
> > > + if (i > 11)
> > > + return -EINVAL;
> > > + break;
> > > + case MT_PHY_TYPE_HE_MU:
> > > + case MT_PHY_TYPE_HE_SU:
> > > + case MT_PHY_TYPE_HE_EXT_SU:
> > > + case MT_PHY_TYPE_HE_TB:
> > > + status->nss = nss;
> > > + status->encoding = RX_ENC_HE;
> > > + i &= GENMASK(3, 0);
> > > +
> > > + if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
> > > + status->he_gi = gi;
> > > +
> > > + status->he_dcm = dcm;
> > > + break;
> > > + case MT_PHY_TYPE_EHT_SU:
> > > + case MT_PHY_TYPE_EHT_TRIG:
> > > + case MT_PHY_TYPE_EHT_MU:
> > > + status->nss = nss;
> > > + status->encoding = RX_ENC_EHT;
> > > + i &= GENMASK(3, 0);
> > > +
> > > + if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
> > > + status->eht.gi = gi;
> > > + break;
> > > + default:
> > > + return -EINVAL;
> > > + }
> > > + status->rate_idx = i;
> > > +
> > > + switch (bw) {
> > > + case IEEE80211_STA_RX_BW_20:
> > > + break;
> > > + case IEEE80211_STA_RX_BW_40:
> > > + if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
> > > + (idx & MT_PRXV_TX_ER_SU_106T)) {
> > > + status->bw = RATE_INFO_BW_HE_RU;
> > > + status->he_ru =
> > > + NL80211_RATE_INFO_HE_RU_ALLOC_106;
> > > + } else {
> > > + status->bw = RATE_INFO_BW_40;
> > > + }
> > > + break;
> > > + case IEEE80211_STA_RX_BW_80:
> > > + status->bw = RATE_INFO_BW_80;
> > > + break;
> > > + case IEEE80211_STA_RX_BW_160:
> > > + status->bw = RATE_INFO_BW_160;
> > > + break;
> > > + case IEEE80211_STA_RX_BW_320:
> > > + status->bw = RATE_INFO_BW_320;
> > > + break;
> > > + default:
> > > + return -EINVAL;
> > > + }
> > > +
> > > + status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
> > > + if (*mode < MT_PHY_TYPE_HE_SU && gi)
> > > + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
> > > +
> > > + return 0;
> > > +}
> > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_fill_rx_rate);
> > > +
> > > +static void
> > > +mt76_connac3_mac_write_txwi_8023(__le32 *txwi, struct sk_buff
> > > *skb,
> > > + struct mt76_wcid *wcid)
> > > +{
> > > + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
> > > + u8 fc_type, fc_stype;
> > > + u16 ethertype;
> > > + bool wmm = false;
> > > + u32 val;
> > > +
> > > + if (wcid->sta) {
> > > + struct ieee80211_sta *sta;
> > > +
> > > + sta = container_of((void *)wcid, struct ieee80211_sta,
> > > drv_priv);
> > > + wmm = sta->wme;
> > > + }
> > > +
> > > + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
> > > + FIELD_PREP(MT_TXD1_TID, tid);
> > > +
> > > + ethertype = get_unaligned_be16(&skb->data[12]);
> > > + if (ethertype >= ETH_P_802_3_MIN)
> > > + val |= MT_TXD1_ETH_802_3;
> > > +
> > > + txwi[1] |= cpu_to_le32(val);
> > > +
> > > + fc_type = IEEE80211_FTYPE_DATA >> 2;
> > > + fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0;
> > > +
> > > + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
> > > + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
> > > +
> > > + txwi[2] |= cpu_to_le32(val);
> > > +}
> > > +
> > > +static void
> > > +mt76_connac3_mac_write_txwi_80211(struct mt76_dev *dev, __le32
> > > *txwi,
> > > + struct sk_buff *skb,
> > > + struct ieee80211_key_conf *key)
> > > +{
> > > + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
> > > + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb-
> > > > data;
> > >
> > > + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> > > + bool multicast = is_multicast_ether_addr(hdr->addr1);
> > > + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
> > > + __le16 fc = hdr->frame_control;
> > > + u8 fc_type, fc_stype;
> > > + u32 val;
> > > +
> > > + if (ieee80211_is_action(fc) &&
> > > + mgmt->u.action.category == WLAN_CATEGORY_BACK &&
> > > + mgmt->u.action.u.addba_req.action_code ==
> > > WLAN_ACTION_ADDBA_REQ)
> > > + tid = MT_TX_ADDBA;
> > > + else if (ieee80211_is_mgmt(hdr->frame_control))
> > > + tid = MT_TX_NORMAL;
> > > +
> > > + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
> > > + FIELD_PREP(MT_TXD1_HDR_INFO,
> > > + ieee80211_get_hdrlen_from_skb(skb) / 2) |
> > > + FIELD_PREP(MT_TXD1_TID, tid);
> > > +
> > > + if (!ieee80211_is_data(fc) || multicast ||
> > > + info->flags & IEEE80211_TX_CTL_USE_MINRATE)
> > > + val |= MT_TXD1_FIXED_RATE;
> > > +
> > > + if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
> > > + key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
> > > + val |= MT_TXD1_BIP;
> > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
> > > + }
> > > +
> > > + txwi[1] |= cpu_to_le32(val);
> > > +
> > > + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
> > > + fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
> > > +
> > > + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
> > > + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
> > > +
> > > + txwi[2] |= cpu_to_le32(val);
> > > +
> > > + txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast));
> > > + if (ieee80211_is_beacon(fc)) {
> > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT);
> > > + txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
> > > + }
> > > +
> > > + if (info->flags & IEEE80211_TX_CTL_INJECTED) {
> > > + u16 seqno = le16_to_cpu(hdr->seq_ctrl);
> > > +
> > > + if (ieee80211_is_back_req(hdr->frame_control)) {
> > > + struct ieee80211_bar *bar;
> > > +
> > > + bar = (struct ieee80211_bar *)skb->data;
> > > + seqno = le16_to_cpu(bar->start_seq_num);
> > > + }
> > > +
> > > + val = MT_TXD3_SN_VALID |
> > > + FIELD_PREP(MT_TXD3_SEQ,
> > > IEEE80211_SEQ_TO_SN(seqno));
> > > + txwi[3] |= cpu_to_le32(val);
> > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
> > > + }
> > > +}
> > > +
> > > +void mt76_connac3_mac_write_txwi(struct mt76_dev *dev, __le32
> > > *txwi,
> > > + struct sk_buff *skb, struct mt76_wcid
> > > *wcid,
> > > + struct ieee80211_key_conf *key, int
> > > pid,
> > > + enum mt76_txq_id qid, u32 changed)
> > > +{
> > > + u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE :
> > > MT_SDIO_TXD_SIZE;
> > > + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> > > + struct ieee80211_vif *vif = info->control.vif;
> > > + u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
> > > + u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
> > > + bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
> > > + struct mt76_vif *mvif;
> > > + u16 tx_count = 15;
> > > + bool beacon = !!(changed & (BSS_CHANGED_BEACON |
> > > + BSS_CHANGED_BEACON_ENABLED));
> > > + bool inband_disc = !!(changed &
> > > (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
> > > + BSS_CHANGED_FILS_DISCOVERY));
> > > +
> > > + mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL;
> > > + if (mvif) {
> > > + omac_idx = mvif->omac_idx;
> > > + wmm_idx = mvif->wmm_idx;
> > > + band_idx = mvif->band_idx;
> > > + }
> > > +
> > > + if (inband_disc) {
> > > + p_fmt = MT_TX_TYPE_FW;
> > > + q_idx = MT_LMAC_ALTX0;
> > > + } else if (beacon) {
> > > + p_fmt = MT_TX_TYPE_FW;
> > > + q_idx = MT_LMAC_BCN0;
> > > + } else if (qid >= MT_TXQ_PSD) {
> > > + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT :
> > > MT_TX_TYPE_SF;
> > > + q_idx = MT_LMAC_ALTX0;
> > > + } else {
> > > + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT :
> > > MT_TX_TYPE_SF;
> > > + q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS +
> > > + mt76_connac_lmac_mapping(skb_get_queue_mapping(
> > > skb));
> > > + }
> > > +
> > > + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
> > > + FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
> > > + FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
> > > + txwi[0] = cpu_to_le32(val);
> > > +
> > > + val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
> > > + FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
> > > +
> > > + if (band_idx)
> > > + val |= FIELD_PREP(MT_TXD1_TGID, band_idx);
> > > +
> > > + txwi[1] = cpu_to_le32(val);
> > > + txwi[2] = 0;
> > > +
> > > + val = MT_TXD3_SW_POWER_MGMT |
> > > + FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count);
> > > + if (key)
> > > + val |= MT_TXD3_PROTECT_FRAME;
> > > + if (info->flags & IEEE80211_TX_CTL_NO_ACK)
> > > + val |= MT_TXD3_NO_ACK;
> > > + if (wcid->amsdu)
> > > + val |= MT_TXD3_HW_AMSDU;
> > > +
> > > + txwi[3] = cpu_to_le32(val);
> > > + txwi[4] = 0;
> > > +
> > > + val = FIELD_PREP(MT_TXD5_PID, pid);
> > > + if (pid >= MT_PACKET_ID_FIRST)
> > > + val |= MT_TXD5_TX_STATUS_HOST;
> > > + txwi[5] = cpu_to_le32(val);
> > > +
> > > + val = MT_TXD6_DIS_MAT | MT_TXD6_DAS |
> > > + FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
> > > + txwi[6] = cpu_to_le32(val);
> > > + txwi[7] = 0;
> > > +
> > > + if (is_8023)
> > > + mt76_connac3_mac_write_txwi_8023(txwi, skb, wcid);
> > > + else
> > > + mt76_connac3_mac_write_txwi_80211(dev, txwi, skb, key);
> > > +
> > > + if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
> > > + struct ieee80211_hdr *hdr = (struct ieee80211_hdr
> > > *)skb->data;
> > > + bool mcast = ieee80211_is_data(hdr->frame_control) &&
> > > + is_multicast_ether_addr(hdr->addr1);
> > > + u8 idx = MT76_CONNAC3_BASIC_RATES_TBL;
> > > +
> > > + if (mvif) {
> > > + if (mcast && mvif->mcast_rates_idx)
> > > + idx = mvif->mcast_rates_idx;
> > > + else if (beacon && mvif->beacon_rates_idx)
> > > + idx = mvif->beacon_rates_idx;
> > > + else
> > > + idx = mvif->basic_rates_idx;
> > > + }
> > > +
> > > + txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE,
> > > idx));
> > > + txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
> > > + }
> > > +}
> > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_write_txwi);
> > > +
> > > +void mt76_connac3_txwi_free(struct mt76_dev *dev, struct
> > > mt76_txwi_cache *t,
> > > + struct ieee80211_sta *sta,
> > > + struct list_head *free_list)
> > > +{
> > > + __le32 *txwi;
> > > + u16 wcid_idx;
> > > +
> > > + mt76_connac_txp_skb_unmap(dev, t);
> > > + if (!t->skb)
> > > + goto out;
> > > +
> > > + txwi = (__le32 *)mt76_get_txwi_ptr(dev, t);
> > > + if (sta) {
> > > + struct mt76_wcid *wcid = (struct mt76_wcid *)sta-
> > > > drv_priv;
> > >
> > > +
> > > + wcid_idx = wcid->idx;
> > > + if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
> > > + mt76_connac3_tx_check_aggr(sta, txwi);
> > > + } else {
> > > + wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
> > > + }
> > > +
> > > + __mt76_tx_complete_skb(dev, wcid_idx, t->skb, free_list);
> > > +out:
> > > + t->skb = NULL;
> > > + mt76_put_txwi(dev, t);
> > > +}
> > > +EXPORT_SYMBOL_GPL(mt76_connac3_txwi_free);
> > > +
> > > +static bool
> > > +mt76_connac3_mac_add_txs_skb(struct mt76_dev *dev, struct
> > > mt76_wcid
> > > *wcid,
> > > + int pid, __le32 *txs_data)
> > > +{
> > > + struct mt76_sta_stats *stats = &wcid->stats;
> > > + struct ieee80211_supported_band *sband;
> > > + struct ieee80211_tx_info *info;
> > > + u32 txrate, txs, mode, stbc;
> > > + struct rate_info rate = {};
> > > + struct sk_buff_head list;
> > > + struct mt76_phy *mphy;
> > > + struct sk_buff *skb;
> > > + bool cck = false;
> > > +
> > > + mt76_tx_status_lock(dev, &list);
> > > + skb = mt76_tx_status_skb_get(dev, wcid, pid, &list);
> > > + if (!skb)
> > > + goto out_no_skb;
> > > +
> > > + txs = le32_to_cpu(txs_data[0]);
> > > +
> > > + info = IEEE80211_SKB_CB(skb);
> > > + if (!(txs & MT_TXS0_ACK_ERROR_MASK))
> > > + info->flags |= IEEE80211_TX_STAT_ACK;
> > > +
> > > + info->status.ampdu_len = 1;
> > > + info->status.ampdu_ack_len = !!(info->flags &
> > > + IEEE80211_TX_STAT_ACK);
> > > + info->status.rates[0].idx = -1;
> > > +
> > > + txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
> > > +
> > > + rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
> > > + rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
> > > + stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC);
> > > +
> > > + if (stbc && rate.nss > 1)
> > > + rate.nss >>= 1;
> > > +
> > > + if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
> > > + stats->tx_nss[rate.nss - 1]++;
> > > + if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
> > > + stats->tx_mcs[rate.mcs]++;
> > > +
> > > + mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
> > > + switch (mode) {
> > > + case MT_PHY_TYPE_CCK:
> > > + cck = true;
> > > + fallthrough;
> > > + case MT_PHY_TYPE_OFDM:
> > > + mphy = mt76_dev_phy(dev, wcid->phy_idx);
> > > +
> > > + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
> > > + sband = &mphy->sband_5g.sband;
> > > + else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
> > > + sband = &mphy->sband_6g.sband;
> > > + else
> > > + sband = &mphy->sband_2g.sband;
> > > +
> > > + rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs,
> > > cck);
> > > + rate.legacy = sband->bitrates[rate.mcs].bitrate;
> > > + break;
> > > + case MT_PHY_TYPE_HT:
> > > + case MT_PHY_TYPE_HT_GF:
> > > + if (rate.mcs > 31)
> > > + goto out;
> > > +
> > > + rate.flags = RATE_INFO_FLAGS_MCS;
> > > + if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
> > > + rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
> > > + break;
> > > + case MT_PHY_TYPE_VHT:
> > > + if (rate.mcs > 9)
> > > + goto out;
> > > +
> > > + rate.flags = RATE_INFO_FLAGS_VHT_MCS;
> > > + break;
> > > + case MT_PHY_TYPE_HE_SU:
> > > + case MT_PHY_TYPE_HE_EXT_SU:
> > > + case MT_PHY_TYPE_HE_TB:
> > > + case MT_PHY_TYPE_HE_MU:
> > > + if (rate.mcs > 11)
> > > + goto out;
> > > +
> > > + rate.he_gi = wcid->rate.he_gi;
> > > + rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
> > > + rate.flags = RATE_INFO_FLAGS_HE_MCS;
> > > + break;
> > > + case MT_PHY_TYPE_EHT_SU:
> > > + case MT_PHY_TYPE_EHT_TRIG:
> > > + case MT_PHY_TYPE_EHT_MU:
> > > + if (rate.mcs > 13)
> > > + goto out;
> > > +
> > > + rate.eht_gi = wcid->rate.eht_gi;
> > > + rate.flags = RATE_INFO_FLAGS_EHT_MCS;
> > > + break;
> > > + default:
> > > + goto out;
> > > + }
> > > +
> > > + stats->tx_mode[mode]++;
> > > +
> > > + switch (FIELD_GET(MT_TXS0_BW, txs)) {
> > > + case IEEE80211_STA_RX_BW_320:
> > > + rate.bw = RATE_INFO_BW_320;
> > > + stats->tx_bw[4]++;
> > > + break;
> > > + case IEEE80211_STA_RX_BW_160:
> > > + rate.bw = RATE_INFO_BW_160;
> > > + stats->tx_bw[3]++;
> > > + break;
> > > + case IEEE80211_STA_RX_BW_80:
> > > + rate.bw = RATE_INFO_BW_80;
> > > + stats->tx_bw[2]++;
> > > + break;
> > > + case IEEE80211_STA_RX_BW_40:
> > > + rate.bw = RATE_INFO_BW_40;
> > > + stats->tx_bw[1]++;
> > > + break;
> > > + default:
> > > + rate.bw = RATE_INFO_BW_20;
> > > + stats->tx_bw[0]++;
> > > + break;
> > > + }
> > > + wcid->rate = rate;
> > > +
> > > +out:
> > > + mt76_tx_status_skb_done(dev, skb, &list);
> > > +
> > > +out_no_skb:
> > > + mt76_tx_status_unlock(dev, &list);
> > > +
> > > + return !!skb;
> > > +}
> > > +
> > > +void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void *data,
> > > + u32 max_wtbl_size)
> > > +{
> > > + struct mt76_wcid *wcid;
> > > + __le32 *txs_data = data;
> > > + u16 wcidx;
> > > + u8 pid;
> > > +
> > > + if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
> > > + return;
> > > +
> > > + wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
> > > + pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
> > > +
> > > + if (pid < MT_PACKET_ID_FIRST)
> > > + return;
> > > +
> > > + if (wcidx >= max_wtbl_size)
> > > + return;
> > > +
> > > + rcu_read_lock();
> > > +
> > > + wcid = rcu_dereference(dev->wcid[wcidx]);
> > > + if (!wcid)
> > > + goto out;
> > > +
> > > + mt76_connac3_mac_add_txs_skb(dev, wcid, pid, txs_data);
> > > + if (!wcid->sta)
> > > + goto out;
> > > +
> > > + spin_lock_bh(&dev->sta_poll_lock);
> > > + if (list_empty(&wcid->poll_list))
> > > + list_add_tail(&wcid->poll_list, &dev->sta_poll_list);
> > > + spin_unlock_bh(&dev->sta_poll_lock);
> > > +
> > > +out:
> > > + rcu_read_unlock();
> > > +}
> > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_add_txs);
> > > +
> > > +void mt76_connac3_tx_token_put(struct mt76_dev *dev)
> > > +{
> > > + struct mt76_txwi_cache *txwi;
> > > + int id;
> > > +
> > > + spin_lock_bh(&dev->token_lock);
> > > + idr_for_each_entry(&dev->token, txwi, id) {
> > > + mt76_connac3_txwi_free(dev, txwi, NULL, NULL);
> > > + dev->token_count--;
> > > + }
> > > + spin_unlock_bh(&dev->token_lock);
> > > + idr_destroy(&dev->token);
> > > +}
> > > +EXPORT_SYMBOL_GPL(mt76_connac3_tx_token_put);
> > > diff --git
> > > a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > index 6663a0b46541..bcc1d976b2b0 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > @@ -4,6 +4,24 @@
> > > #ifndef __MT76_CONNAC3_MAC_H
> > > #define __MT76_CONNAC3_MAC_H
> > >
> > > +/* NOTE: used to map mt76_rates. idx may change if firmware
> > > expands
> > > table */
> > > +#define MT76_CONNAC3_BASIC_RATES_TBL 11
> > > +#define MT76_CONNAC3_BEACON_RATES_TBL 25
> > >
> >
> > Different devices may have different defined value.
>
> The other WiFi7 device I am working on relies on the values I moved
> in
> mt76_connac3_mac.h (in common with mt7996). Moreover you can still
> have per-device values in mt7996/mac.h (I have not removed it).
>
Please double check with the mtk folk you work with. The 11 and 25 is
the value I discussed with firmware folks to avoid overlapping the tbl
mt7996 use (MU/other algo in fw), or it causes something hardly solving
issue
> >
> > I'm thinking if it's too early to create this patch for just moving
> > mt7996 to connac3_lib?
>
> The code I moved is used by the other device as well. This series is
> a
> preliminary series to support it.
>
> Regards,
> Lorenzo
>
> >
> > Ryder
> >
^ permalink raw reply [flat|nested] 27+ messages in thread* Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library
2023-06-09 16:38 ` Ryder Lee
@ 2023-06-09 16:45 ` lorenzo
[not found] ` <PH8PR12MB7230DC95457EF9C667E679AEAC51A@PH8PR12MB7230.namprd12.prod.outlook.com>
2023-06-10 2:22 ` Deren Wu (武德仁)
0 siblings, 2 replies; 27+ messages in thread
From: lorenzo @ 2023-06-09 16:45 UTC (permalink / raw)
To: Ryder Lee
Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org,
nbd@nbd.name, Deren Wu
[-- Attachment #1: Type: text/plain, Size: 33683 bytes --]
> On Fri, 2023-06-09 at 18:34 +0200, lorenzo.bianconi@redhat.com wrote:
> > On Jun 09, Ryder Lee wrote:
> > > On Fri, 2023-06-09 at 10:15 +0200, Lorenzo Bianconi wrote:
> > > >
> > > > External email : Please do not click links or open attachments
> > > > until
> > > > you have verified the sender or the content.
> > > > Introduce connac3_mac in mt76_connac library to reuse mac code
> > > > shared
> > > > between WiFi7 chipsets.
> > > >
> > > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > ---
> > > > drivers/net/wireless/mediatek/mt76/Makefile | 2 +-
> > > > .../net/wireless/mediatek/mt76/mt76_connac.h | 19 +
> > > > .../wireless/mediatek/mt76/mt76_connac3_mac.c | 742
> > > > +++++++++++++++++
> > > > .../wireless/mediatek/mt76/mt76_connac3_mac.h | 18 +
> > > > .../net/wireless/mediatek/mt76/mt7996/init.c | 4 +-
> > > > .../net/wireless/mediatek/mt76/mt7996/mac.c | 761 +-----------
> > > > ----
> > > > --
> > > > .../net/wireless/mediatek/mt76/mt7996/main.c | 8 +-
> > > > .../net/wireless/mediatek/mt76/mt7996/mcu.c | 9 +-
> > > > .../wireless/mediatek/mt76/mt7996/mt7996.h | 28 +-
> > > > 9 files changed, 807 insertions(+), 784 deletions(-)
> > > > create mode 100644
> > > > drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > >
> > > > diff --git a/drivers/net/wireless/mediatek/mt76/Makefile
> > > > b/drivers/net/wireless/mediatek/mt76/Makefile
> > > > index 84c99b7e57f9..d8e8079c8b54 100644
> > > > --- a/drivers/net/wireless/mediatek/mt76/Makefile
> > > > +++ b/drivers/net/wireless/mediatek/mt76/Makefile
> > > > @@ -27,7 +27,7 @@ mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o
> > > > mt76x02_mcu.o \
> > > >
> > > > mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
> > > >
> > > > -mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
> > > > +mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
> > > > mt76_connac3_mac.o
> > > >
> > > > obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
> > > > obj-$(CONFIG_MT76x2_COMMON) += mt76x2/
> > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > > b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > > index 68bdeada1421..20111678537b 100644
> > > > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > > @@ -415,4 +415,23 @@ void mt76_connac2_txwi_free(struct mt76_dev
> > > > *dev, struct mt76_txwi_cache *t,
> > > > struct list_head *free_list);
> > > > void mt76_connac2_tx_token_put(struct mt76_dev *dev);
> > > >
> > > > +/* connac3 */
> > > > +void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta,
> > > > __le32
> > > > *txwi);
> > > > +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb,
> > > > __le32
> > > > *rxv,
> > > > + u8 mode);
> > > > +int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev,
> > > > + struct mt76_rx_status *status,
> > > > + struct ieee80211_supported_band
> > > > *sband,
> > > > + __le32 *rxv, u8 *mode);
> > > > +void mt76_connac3_mac_write_txwi(struct mt76_dev *dev, __le32
> > > > *txwi,
> > > > + struct sk_buff *skb, struct mt76_wcid
> > > > *wcid,
> > > > + struct ieee80211_key_conf *key, int
> > > > pid,
> > > > + enum mt76_txq_id qid, u32 changed);
> > > > +void mt76_connac3_txwi_free(struct mt76_dev *dev, struct
> > > > mt76_txwi_cache *t,
> > > > + struct ieee80211_sta *sta,
> > > > + struct list_head *free_list);
> > > > +void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void *data,
> > > > + u32 max_wtbl_size);
> > > > +void mt76_connac3_tx_token_put(struct mt76_dev *dev);
> > > > +
> > > > #endif /* __MT76_CONNAC_H */
> > > > diff --git
> > > > a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > > b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > > new file mode 100644
> > > > index 000000000000..4b745bb74ca0
> > > > --- /dev/null
> > > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > > @@ -0,0 +1,742 @@
> > > > +// SPDX-License-Identifier: ISC
> > > > +/* Copyright (C) 2023 MediaTek Inc. */
> > > > +
> > > > +#include "mt76_connac.h"
> > > > +#include "mt76_connac3_mac.h"
> > > > +#include "dma.h"
> > > > +
> > > > +#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_
> > > > HE_##f)
> > > > +#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v,
> > > > MT_CRXV_HE_##m),\
> > > > + IEEE80211_RADIOTAP_HE_
> > > > ##f)
> > > > +
> > > > +void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta,
> > > > __le32
> > > > *txwi)
> > > > +{
> > > > + struct mt76_wcid *wcid;
> > > > + u16 fc, tid;
> > > > + u32 val;
> > > > +
> > > > + if (!sta ||
> > > > + !(sta->deflink.ht_cap.ht_supported || sta-
> > > > > deflink.he_cap.has_he))
> > > >
> > > > + return;
> > > > +
> > > > + tid = le32_get_bits(txwi[1], MT_TXD1_TID);
> > > > + if (tid >= 6) /* skip VO queue */
> > > > + return;
> > > > +
> > > > + val = le32_to_cpu(txwi[2]);
> > > > + fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
> > > > + FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
> > > > + if (unlikely(fc != (IEEE80211_FTYPE_DATA |
> > > > IEEE80211_STYPE_QOS_DATA)))
> > > > + return;
> > > > +
> > > > + wcid = (struct mt76_wcid *)sta->drv_priv;
> > > > + if (!test_and_set_bit(tid, &wcid->ampdu_state))
> > > > + ieee80211_start_tx_ba_session(sta, tid, 0);
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(mt76_connac3_tx_check_aggr);
> > > > +
> > > > +static void
> > > > +mt76_connac3_mac_decode_he_radiotap_ru(struct mt76_rx_status
> > > > *status,
> > > > + struct ieee80211_radiotap_he
> > > > *he,
> > > > + __le32 *rxv)
> > > > +{
> > > > + u32 ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC), offs = 0;
> > > > +
> > > > + status->bw = RATE_INFO_BW_HE_RU;
> > > > +
> > > > + switch (ru) {
> > > > + case 0 ... 36:
> > > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
> > > > + offs = ru;
> > > > + break;
> > > > + case 37 ... 52:
> > > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
> > > > + offs = ru - 37;
> > > > + break;
> > > > + case 53 ... 60:
> > > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
> > > > + offs = ru - 53;
> > > > + break;
> > > > + case 61 ... 64:
> > > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
> > > > + offs = ru - 61;
> > > > + break;
> > > > + case 65 ... 66:
> > > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
> > > > + offs = ru - 65;
> > > > + break;
> > > > + case 67:
> > > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
> > > > + break;
> > > > + case 68:
> > > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
> > > > + break;
> > > > + }
> > > > +
> > > > + he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > > > + he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
> > > > + le16_encode_bits(offs,
> > > > + IEEE80211_RADIOTAP_HE_DATA2_RU_OF
> > > > FSET);
> > > > +}
> > > > +
> > > > +#define MU_PREP(f, v) le16_encode_bits(v,
> > > > IEEE80211_RADIOTAP_HE_MU_##f)
> > > > +static void
> > > > +mt76_connac3_mac_decode_he_mu_radiotap(struct sk_buff *skb,
> > > > __le32
> > > > *rxv)
> > > > +{
> > > > + struct mt76_rx_status *status = (struct mt76_rx_status *)skb-
> > > > > cb;
> > > >
> > > > + static const struct ieee80211_radiotap_he_mu mu_known = {
> > > > + .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
> > > > + HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
> > > > + HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
> > > > + HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN),
> > > > + .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
> > > > + };
> > > > + struct ieee80211_radiotap_he_mu *he_mu;
> > > > +
> > > > + status->flag |= RX_FLAG_RADIOTAP_HE_MU;
> > > > +
> > > > + he_mu = skb_push(skb, sizeof(mu_known));
> > > > + memcpy(he_mu, &mu_known, sizeof(mu_known));
> > > > +
> > > > + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
> > > > + if (status->he_dcm)
> > > > + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status-
> > > > > he_dcm);
> > > >
> > > > +
> > > > + he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
> > > > + MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
> > > > + le32_get_bits(rxv[4],
> > > > MT_CRXV_HE_NUM_USER));
> > > > +
> > > > + he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) &
> > > > 0xff;
> > > > +
> > > > + if (status->bw >= RATE_INFO_BW_40) {
> > > > + he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
> > > > + he_mu->ru_ch2[0] = le32_get_bits(rxv[16],
> > > > MT_CRXV_HE_RU1) & 0xff;
> > > > + }
> > > > +
> > > > + if (status->bw >= RATE_INFO_BW_80) {
> > > > + u32 ru_h, ru_l;
> > > > +
> > > > + he_mu->ru_ch1[1] = le32_get_bits(rxv[16],
> > > > MT_CRXV_HE_RU2) & 0xff;
> > > > +
> > > > + ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L);
> > > > + ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7;
> > > > + he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4);
> > > > + }
> > > > +}
> > > > +
> > > > +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb,
> > > > __le32
> > > > *rxv,
> > > > + u8 mode)
> > > > +{
> > > > + struct mt76_rx_status *status = (struct mt76_rx_status *)skb-
> > > > > cb;
> > > >
> > > > + static const struct ieee80211_radiotap_he known = {
> > > > + .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
> > > > + HE_BITS(DATA1_DATA_DCM_KNOWN) |
> > > > + HE_BITS(DATA1_STBC_KNOWN) |
> > > > + HE_BITS(DATA1_CODING_KNOWN) |
> > > > + HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
> > > > + HE_BITS(DATA1_DOPPLER_KNOWN) |
> > > > + HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
> > > > + HE_BITS(DATA1_BSS_COLOR_KNOWN),
> > > > + .data2 = HE_BITS(DATA2_GI_KNOWN) |
> > > > + HE_BITS(DATA2_TXBF_KNOWN) |
> > > > + HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
> > > > + HE_BITS(DATA2_TXOP_KNOWN),
> > > > + };
> > > > + u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1;
> > > > + struct ieee80211_radiotap_he *he;
> > > > +
> > > > + status->flag |= RX_FLAG_RADIOTAP_HE;
> > > > +
> > > > + he = skb_push(skb, sizeof(known));
> > > > + memcpy(he, &known, sizeof(known));
> > > > +
> > > > + he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) |
> > > > + HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]);
> > > > + he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]);
> > > > + he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) |
> > > > + le16_encode_bits(ltf_size,
> > > > + IEEE80211_RADIOTAP_HE_DATA5_LTF_SI
> > > > ZE);
> > > > + if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
> > > > + he->data5 |= HE_BITS(DATA5_TXBF);
> > > > + he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) |
> > > > + HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]);
> > > > +
> > > > + switch (mode) {
> > > > + case MT_PHY_TYPE_HE_SU:
> > > > + he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
> > > > + HE_BITS(DATA1_UL_DL_KNOWN) |
> > > > + HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
> > > > + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > > > +
> > > > + he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG,
> > > > rxv[8]) |
> > > > + HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
> > > > + break;
> > > > + case MT_PHY_TYPE_HE_EXT_SU:
> > > > + he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
> > > > + HE_BITS(DATA1_UL_DL_KNOWN) |
> > > > + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > > > +
> > > > + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
> > > > + break;
> > > > + case MT_PHY_TYPE_HE_MU:
> > > > + he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
> > > > + HE_BITS(DATA1_UL_DL_KNOWN);
> > > > +
> > > > + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
> > > > + he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]);
> > > > +
> > > > + mt76_connac3_mac_decode_he_radiotap_ru(status, he,
> > > > rxv);
> > > > + mt76_connac3_mac_decode_he_mu_radiotap(skb, rxv);
> > > > + break;
> > > > + case MT_PHY_TYPE_HE_TB:
> > > > + he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
> > > > + HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
> > > > + HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
> > > > + HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
> > > > +
> > > > + he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK,
> > > > rxv[13]) |
> > > > + HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK,
> > > > rxv[13]) |
> > > > + HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK,
> > > > rxv[13]) |
> > > > + HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK,
> > > > rxv[13]);
> > > > +
> > > > + mt76_connac3_mac_decode_he_radiotap_ru(status, he,
> > > > rxv);
> > > > + break;
> > > > + default:
> > > > + break;
> > > > + }
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap);
> > > > +
> > > > +int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev,
> > > > + struct mt76_rx_status *status,
> > > > + struct ieee80211_supported_band
> > > > *sband,
> > > > + __le32 *rxv, u8 *mode)
> > > > +{
> > > > + u8 stbc, gi, bw, dcm, nss;
> > > > + bool cck = false;
> > > > + u32 v0, v2;
> > > > + int i, idx;
> > > > +
> > > > + v0 = le32_to_cpu(rxv[0]);
> > > > + v2 = le32_to_cpu(rxv[2]);
> > > > +
> > > > + idx = FIELD_GET(MT_PRXV_TX_RATE, v0);
> > > > + i = idx;
> > > > + nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1;
> > > > +
> > > > + stbc = FIELD_GET(MT_PRXV_HT_STBC, v2);
> > > > + gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2);
> > > > + *mode = FIELD_GET(MT_PRXV_TX_MODE, v2);
> > > > + dcm = FIELD_GET(MT_PRXV_DCM, v2);
> > > > + bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2);
> > > > +
> > > > + switch (*mode) {
> > > > + case MT_PHY_TYPE_CCK:
> > > > + cck = true;
> > > > + fallthrough;
> > > > + case MT_PHY_TYPE_OFDM:
> > > > + i = mt76_get_rate(dev, sband, i, cck);
> > > > + break;
> > > > + case MT_PHY_TYPE_HT_GF:
> > > > + case MT_PHY_TYPE_HT:
> > > > + status->encoding = RX_ENC_HT;
> > > > + if (gi)
> > > > + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
> > > > + if (i > 31)
> > > > + return -EINVAL;
> > > > + break;
> > > > + case MT_PHY_TYPE_VHT:
> > > > + status->nss = nss;
> > > > + status->encoding = RX_ENC_VHT;
> > > > + if (gi)
> > > > + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
> > > > + if (i > 11)
> > > > + return -EINVAL;
> > > > + break;
> > > > + case MT_PHY_TYPE_HE_MU:
> > > > + case MT_PHY_TYPE_HE_SU:
> > > > + case MT_PHY_TYPE_HE_EXT_SU:
> > > > + case MT_PHY_TYPE_HE_TB:
> > > > + status->nss = nss;
> > > > + status->encoding = RX_ENC_HE;
> > > > + i &= GENMASK(3, 0);
> > > > +
> > > > + if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
> > > > + status->he_gi = gi;
> > > > +
> > > > + status->he_dcm = dcm;
> > > > + break;
> > > > + case MT_PHY_TYPE_EHT_SU:
> > > > + case MT_PHY_TYPE_EHT_TRIG:
> > > > + case MT_PHY_TYPE_EHT_MU:
> > > > + status->nss = nss;
> > > > + status->encoding = RX_ENC_EHT;
> > > > + i &= GENMASK(3, 0);
> > > > +
> > > > + if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
> > > > + status->eht.gi = gi;
> > > > + break;
> > > > + default:
> > > > + return -EINVAL;
> > > > + }
> > > > + status->rate_idx = i;
> > > > +
> > > > + switch (bw) {
> > > > + case IEEE80211_STA_RX_BW_20:
> > > > + break;
> > > > + case IEEE80211_STA_RX_BW_40:
> > > > + if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
> > > > + (idx & MT_PRXV_TX_ER_SU_106T)) {
> > > > + status->bw = RATE_INFO_BW_HE_RU;
> > > > + status->he_ru =
> > > > + NL80211_RATE_INFO_HE_RU_ALLOC_106;
> > > > + } else {
> > > > + status->bw = RATE_INFO_BW_40;
> > > > + }
> > > > + break;
> > > > + case IEEE80211_STA_RX_BW_80:
> > > > + status->bw = RATE_INFO_BW_80;
> > > > + break;
> > > > + case IEEE80211_STA_RX_BW_160:
> > > > + status->bw = RATE_INFO_BW_160;
> > > > + break;
> > > > + case IEEE80211_STA_RX_BW_320:
> > > > + status->bw = RATE_INFO_BW_320;
> > > > + break;
> > > > + default:
> > > > + return -EINVAL;
> > > > + }
> > > > +
> > > > + status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
> > > > + if (*mode < MT_PHY_TYPE_HE_SU && gi)
> > > > + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
> > > > +
> > > > + return 0;
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_fill_rx_rate);
> > > > +
> > > > +static void
> > > > +mt76_connac3_mac_write_txwi_8023(__le32 *txwi, struct sk_buff
> > > > *skb,
> > > > + struct mt76_wcid *wcid)
> > > > +{
> > > > + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
> > > > + u8 fc_type, fc_stype;
> > > > + u16 ethertype;
> > > > + bool wmm = false;
> > > > + u32 val;
> > > > +
> > > > + if (wcid->sta) {
> > > > + struct ieee80211_sta *sta;
> > > > +
> > > > + sta = container_of((void *)wcid, struct ieee80211_sta,
> > > > drv_priv);
> > > > + wmm = sta->wme;
> > > > + }
> > > > +
> > > > + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
> > > > + FIELD_PREP(MT_TXD1_TID, tid);
> > > > +
> > > > + ethertype = get_unaligned_be16(&skb->data[12]);
> > > > + if (ethertype >= ETH_P_802_3_MIN)
> > > > + val |= MT_TXD1_ETH_802_3;
> > > > +
> > > > + txwi[1] |= cpu_to_le32(val);
> > > > +
> > > > + fc_type = IEEE80211_FTYPE_DATA >> 2;
> > > > + fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0;
> > > > +
> > > > + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
> > > > + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
> > > > +
> > > > + txwi[2] |= cpu_to_le32(val);
> > > > +}
> > > > +
> > > > +static void
> > > > +mt76_connac3_mac_write_txwi_80211(struct mt76_dev *dev, __le32
> > > > *txwi,
> > > > + struct sk_buff *skb,
> > > > + struct ieee80211_key_conf *key)
> > > > +{
> > > > + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
> > > > + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb-
> > > > > data;
> > > >
> > > > + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> > > > + bool multicast = is_multicast_ether_addr(hdr->addr1);
> > > > + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
> > > > + __le16 fc = hdr->frame_control;
> > > > + u8 fc_type, fc_stype;
> > > > + u32 val;
> > > > +
> > > > + if (ieee80211_is_action(fc) &&
> > > > + mgmt->u.action.category == WLAN_CATEGORY_BACK &&
> > > > + mgmt->u.action.u.addba_req.action_code ==
> > > > WLAN_ACTION_ADDBA_REQ)
> > > > + tid = MT_TX_ADDBA;
> > > > + else if (ieee80211_is_mgmt(hdr->frame_control))
> > > > + tid = MT_TX_NORMAL;
> > > > +
> > > > + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
> > > > + FIELD_PREP(MT_TXD1_HDR_INFO,
> > > > + ieee80211_get_hdrlen_from_skb(skb) / 2) |
> > > > + FIELD_PREP(MT_TXD1_TID, tid);
> > > > +
> > > > + if (!ieee80211_is_data(fc) || multicast ||
> > > > + info->flags & IEEE80211_TX_CTL_USE_MINRATE)
> > > > + val |= MT_TXD1_FIXED_RATE;
> > > > +
> > > > + if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
> > > > + key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
> > > > + val |= MT_TXD1_BIP;
> > > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
> > > > + }
> > > > +
> > > > + txwi[1] |= cpu_to_le32(val);
> > > > +
> > > > + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
> > > > + fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
> > > > +
> > > > + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
> > > > + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
> > > > +
> > > > + txwi[2] |= cpu_to_le32(val);
> > > > +
> > > > + txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast));
> > > > + if (ieee80211_is_beacon(fc)) {
> > > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT);
> > > > + txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
> > > > + }
> > > > +
> > > > + if (info->flags & IEEE80211_TX_CTL_INJECTED) {
> > > > + u16 seqno = le16_to_cpu(hdr->seq_ctrl);
> > > > +
> > > > + if (ieee80211_is_back_req(hdr->frame_control)) {
> > > > + struct ieee80211_bar *bar;
> > > > +
> > > > + bar = (struct ieee80211_bar *)skb->data;
> > > > + seqno = le16_to_cpu(bar->start_seq_num);
> > > > + }
> > > > +
> > > > + val = MT_TXD3_SN_VALID |
> > > > + FIELD_PREP(MT_TXD3_SEQ,
> > > > IEEE80211_SEQ_TO_SN(seqno));
> > > > + txwi[3] |= cpu_to_le32(val);
> > > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
> > > > + }
> > > > +}
> > > > +
> > > > +void mt76_connac3_mac_write_txwi(struct mt76_dev *dev, __le32
> > > > *txwi,
> > > > + struct sk_buff *skb, struct mt76_wcid
> > > > *wcid,
> > > > + struct ieee80211_key_conf *key, int
> > > > pid,
> > > > + enum mt76_txq_id qid, u32 changed)
> > > > +{
> > > > + u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE :
> > > > MT_SDIO_TXD_SIZE;
> > > > + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> > > > + struct ieee80211_vif *vif = info->control.vif;
> > > > + u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
> > > > + u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
> > > > + bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
> > > > + struct mt76_vif *mvif;
> > > > + u16 tx_count = 15;
> > > > + bool beacon = !!(changed & (BSS_CHANGED_BEACON |
> > > > + BSS_CHANGED_BEACON_ENABLED));
> > > > + bool inband_disc = !!(changed &
> > > > (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
> > > > + BSS_CHANGED_FILS_DISCOVERY));
> > > > +
> > > > + mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL;
> > > > + if (mvif) {
> > > > + omac_idx = mvif->omac_idx;
> > > > + wmm_idx = mvif->wmm_idx;
> > > > + band_idx = mvif->band_idx;
> > > > + }
> > > > +
> > > > + if (inband_disc) {
> > > > + p_fmt = MT_TX_TYPE_FW;
> > > > + q_idx = MT_LMAC_ALTX0;
> > > > + } else if (beacon) {
> > > > + p_fmt = MT_TX_TYPE_FW;
> > > > + q_idx = MT_LMAC_BCN0;
> > > > + } else if (qid >= MT_TXQ_PSD) {
> > > > + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT :
> > > > MT_TX_TYPE_SF;
> > > > + q_idx = MT_LMAC_ALTX0;
> > > > + } else {
> > > > + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT :
> > > > MT_TX_TYPE_SF;
> > > > + q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS +
> > > > + mt76_connac_lmac_mapping(skb_get_queue_mapping(
> > > > skb));
> > > > + }
> > > > +
> > > > + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
> > > > + FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
> > > > + FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
> > > > + txwi[0] = cpu_to_le32(val);
> > > > +
> > > > + val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
> > > > + FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
> > > > +
> > > > + if (band_idx)
> > > > + val |= FIELD_PREP(MT_TXD1_TGID, band_idx);
> > > > +
> > > > + txwi[1] = cpu_to_le32(val);
> > > > + txwi[2] = 0;
> > > > +
> > > > + val = MT_TXD3_SW_POWER_MGMT |
> > > > + FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count);
> > > > + if (key)
> > > > + val |= MT_TXD3_PROTECT_FRAME;
> > > > + if (info->flags & IEEE80211_TX_CTL_NO_ACK)
> > > > + val |= MT_TXD3_NO_ACK;
> > > > + if (wcid->amsdu)
> > > > + val |= MT_TXD3_HW_AMSDU;
> > > > +
> > > > + txwi[3] = cpu_to_le32(val);
> > > > + txwi[4] = 0;
> > > > +
> > > > + val = FIELD_PREP(MT_TXD5_PID, pid);
> > > > + if (pid >= MT_PACKET_ID_FIRST)
> > > > + val |= MT_TXD5_TX_STATUS_HOST;
> > > > + txwi[5] = cpu_to_le32(val);
> > > > +
> > > > + val = MT_TXD6_DIS_MAT | MT_TXD6_DAS |
> > > > + FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
> > > > + txwi[6] = cpu_to_le32(val);
> > > > + txwi[7] = 0;
> > > > +
> > > > + if (is_8023)
> > > > + mt76_connac3_mac_write_txwi_8023(txwi, skb, wcid);
> > > > + else
> > > > + mt76_connac3_mac_write_txwi_80211(dev, txwi, skb, key);
> > > > +
> > > > + if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
> > > > + struct ieee80211_hdr *hdr = (struct ieee80211_hdr
> > > > *)skb->data;
> > > > + bool mcast = ieee80211_is_data(hdr->frame_control) &&
> > > > + is_multicast_ether_addr(hdr->addr1);
> > > > + u8 idx = MT76_CONNAC3_BASIC_RATES_TBL;
> > > > +
> > > > + if (mvif) {
> > > > + if (mcast && mvif->mcast_rates_idx)
> > > > + idx = mvif->mcast_rates_idx;
> > > > + else if (beacon && mvif->beacon_rates_idx)
> > > > + idx = mvif->beacon_rates_idx;
> > > > + else
> > > > + idx = mvif->basic_rates_idx;
> > > > + }
> > > > +
> > > > + txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE,
> > > > idx));
> > > > + txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
> > > > + }
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_write_txwi);
> > > > +
> > > > +void mt76_connac3_txwi_free(struct mt76_dev *dev, struct
> > > > mt76_txwi_cache *t,
> > > > + struct ieee80211_sta *sta,
> > > > + struct list_head *free_list)
> > > > +{
> > > > + __le32 *txwi;
> > > > + u16 wcid_idx;
> > > > +
> > > > + mt76_connac_txp_skb_unmap(dev, t);
> > > > + if (!t->skb)
> > > > + goto out;
> > > > +
> > > > + txwi = (__le32 *)mt76_get_txwi_ptr(dev, t);
> > > > + if (sta) {
> > > > + struct mt76_wcid *wcid = (struct mt76_wcid *)sta-
> > > > > drv_priv;
> > > >
> > > > +
> > > > + wcid_idx = wcid->idx;
> > > > + if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
> > > > + mt76_connac3_tx_check_aggr(sta, txwi);
> > > > + } else {
> > > > + wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
> > > > + }
> > > > +
> > > > + __mt76_tx_complete_skb(dev, wcid_idx, t->skb, free_list);
> > > > +out:
> > > > + t->skb = NULL;
> > > > + mt76_put_txwi(dev, t);
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(mt76_connac3_txwi_free);
> > > > +
> > > > +static bool
> > > > +mt76_connac3_mac_add_txs_skb(struct mt76_dev *dev, struct
> > > > mt76_wcid
> > > > *wcid,
> > > > + int pid, __le32 *txs_data)
> > > > +{
> > > > + struct mt76_sta_stats *stats = &wcid->stats;
> > > > + struct ieee80211_supported_band *sband;
> > > > + struct ieee80211_tx_info *info;
> > > > + u32 txrate, txs, mode, stbc;
> > > > + struct rate_info rate = {};
> > > > + struct sk_buff_head list;
> > > > + struct mt76_phy *mphy;
> > > > + struct sk_buff *skb;
> > > > + bool cck = false;
> > > > +
> > > > + mt76_tx_status_lock(dev, &list);
> > > > + skb = mt76_tx_status_skb_get(dev, wcid, pid, &list);
> > > > + if (!skb)
> > > > + goto out_no_skb;
> > > > +
> > > > + txs = le32_to_cpu(txs_data[0]);
> > > > +
> > > > + info = IEEE80211_SKB_CB(skb);
> > > > + if (!(txs & MT_TXS0_ACK_ERROR_MASK))
> > > > + info->flags |= IEEE80211_TX_STAT_ACK;
> > > > +
> > > > + info->status.ampdu_len = 1;
> > > > + info->status.ampdu_ack_len = !!(info->flags &
> > > > + IEEE80211_TX_STAT_ACK);
> > > > + info->status.rates[0].idx = -1;
> > > > +
> > > > + txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
> > > > +
> > > > + rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
> > > > + rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
> > > > + stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC);
> > > > +
> > > > + if (stbc && rate.nss > 1)
> > > > + rate.nss >>= 1;
> > > > +
> > > > + if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
> > > > + stats->tx_nss[rate.nss - 1]++;
> > > > + if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
> > > > + stats->tx_mcs[rate.mcs]++;
> > > > +
> > > > + mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
> > > > + switch (mode) {
> > > > + case MT_PHY_TYPE_CCK:
> > > > + cck = true;
> > > > + fallthrough;
> > > > + case MT_PHY_TYPE_OFDM:
> > > > + mphy = mt76_dev_phy(dev, wcid->phy_idx);
> > > > +
> > > > + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
> > > > + sband = &mphy->sband_5g.sband;
> > > > + else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
> > > > + sband = &mphy->sband_6g.sband;
> > > > + else
> > > > + sband = &mphy->sband_2g.sband;
> > > > +
> > > > + rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs,
> > > > cck);
> > > > + rate.legacy = sband->bitrates[rate.mcs].bitrate;
> > > > + break;
> > > > + case MT_PHY_TYPE_HT:
> > > > + case MT_PHY_TYPE_HT_GF:
> > > > + if (rate.mcs > 31)
> > > > + goto out;
> > > > +
> > > > + rate.flags = RATE_INFO_FLAGS_MCS;
> > > > + if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
> > > > + rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
> > > > + break;
> > > > + case MT_PHY_TYPE_VHT:
> > > > + if (rate.mcs > 9)
> > > > + goto out;
> > > > +
> > > > + rate.flags = RATE_INFO_FLAGS_VHT_MCS;
> > > > + break;
> > > > + case MT_PHY_TYPE_HE_SU:
> > > > + case MT_PHY_TYPE_HE_EXT_SU:
> > > > + case MT_PHY_TYPE_HE_TB:
> > > > + case MT_PHY_TYPE_HE_MU:
> > > > + if (rate.mcs > 11)
> > > > + goto out;
> > > > +
> > > > + rate.he_gi = wcid->rate.he_gi;
> > > > + rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
> > > > + rate.flags = RATE_INFO_FLAGS_HE_MCS;
> > > > + break;
> > > > + case MT_PHY_TYPE_EHT_SU:
> > > > + case MT_PHY_TYPE_EHT_TRIG:
> > > > + case MT_PHY_TYPE_EHT_MU:
> > > > + if (rate.mcs > 13)
> > > > + goto out;
> > > > +
> > > > + rate.eht_gi = wcid->rate.eht_gi;
> > > > + rate.flags = RATE_INFO_FLAGS_EHT_MCS;
> > > > + break;
> > > > + default:
> > > > + goto out;
> > > > + }
> > > > +
> > > > + stats->tx_mode[mode]++;
> > > > +
> > > > + switch (FIELD_GET(MT_TXS0_BW, txs)) {
> > > > + case IEEE80211_STA_RX_BW_320:
> > > > + rate.bw = RATE_INFO_BW_320;
> > > > + stats->tx_bw[4]++;
> > > > + break;
> > > > + case IEEE80211_STA_RX_BW_160:
> > > > + rate.bw = RATE_INFO_BW_160;
> > > > + stats->tx_bw[3]++;
> > > > + break;
> > > > + case IEEE80211_STA_RX_BW_80:
> > > > + rate.bw = RATE_INFO_BW_80;
> > > > + stats->tx_bw[2]++;
> > > > + break;
> > > > + case IEEE80211_STA_RX_BW_40:
> > > > + rate.bw = RATE_INFO_BW_40;
> > > > + stats->tx_bw[1]++;
> > > > + break;
> > > > + default:
> > > > + rate.bw = RATE_INFO_BW_20;
> > > > + stats->tx_bw[0]++;
> > > > + break;
> > > > + }
> > > > + wcid->rate = rate;
> > > > +
> > > > +out:
> > > > + mt76_tx_status_skb_done(dev, skb, &list);
> > > > +
> > > > +out_no_skb:
> > > > + mt76_tx_status_unlock(dev, &list);
> > > > +
> > > > + return !!skb;
> > > > +}
> > > > +
> > > > +void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void *data,
> > > > + u32 max_wtbl_size)
> > > > +{
> > > > + struct mt76_wcid *wcid;
> > > > + __le32 *txs_data = data;
> > > > + u16 wcidx;
> > > > + u8 pid;
> > > > +
> > > > + if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
> > > > + return;
> > > > +
> > > > + wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
> > > > + pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
> > > > +
> > > > + if (pid < MT_PACKET_ID_FIRST)
> > > > + return;
> > > > +
> > > > + if (wcidx >= max_wtbl_size)
> > > > + return;
> > > > +
> > > > + rcu_read_lock();
> > > > +
> > > > + wcid = rcu_dereference(dev->wcid[wcidx]);
> > > > + if (!wcid)
> > > > + goto out;
> > > > +
> > > > + mt76_connac3_mac_add_txs_skb(dev, wcid, pid, txs_data);
> > > > + if (!wcid->sta)
> > > > + goto out;
> > > > +
> > > > + spin_lock_bh(&dev->sta_poll_lock);
> > > > + if (list_empty(&wcid->poll_list))
> > > > + list_add_tail(&wcid->poll_list, &dev->sta_poll_list);
> > > > + spin_unlock_bh(&dev->sta_poll_lock);
> > > > +
> > > > +out:
> > > > + rcu_read_unlock();
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_add_txs);
> > > > +
> > > > +void mt76_connac3_tx_token_put(struct mt76_dev *dev)
> > > > +{
> > > > + struct mt76_txwi_cache *txwi;
> > > > + int id;
> > > > +
> > > > + spin_lock_bh(&dev->token_lock);
> > > > + idr_for_each_entry(&dev->token, txwi, id) {
> > > > + mt76_connac3_txwi_free(dev, txwi, NULL, NULL);
> > > > + dev->token_count--;
> > > > + }
> > > > + spin_unlock_bh(&dev->token_lock);
> > > > + idr_destroy(&dev->token);
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(mt76_connac3_tx_token_put);
> > > > diff --git
> > > > a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > > b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > > index 6663a0b46541..bcc1d976b2b0 100644
> > > > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > > @@ -4,6 +4,24 @@
> > > > #ifndef __MT76_CONNAC3_MAC_H
> > > > #define __MT76_CONNAC3_MAC_H
> > > >
> > > > +/* NOTE: used to map mt76_rates. idx may change if firmware
> > > > expands
> > > > table */
> > > > +#define MT76_CONNAC3_BASIC_RATES_TBL 11
> > > > +#define MT76_CONNAC3_BEACON_RATES_TBL 25
> > > >
> > >
> > > Different devices may have different defined value.
> >
> > The other WiFi7 device I am working on relies on the values I moved
> > in
> > mt76_connac3_mac.h (in common with mt7996). Moreover you can still
> > have per-device values in mt7996/mac.h (I have not removed it).
> >
>
> Please double check with the mtk folk you work with. The 11 and 25 is
> the value I discussed with firmware folks to avoid overlapping the tbl
> mt7996 use (MU/other algo in fw), or it causes something hardly solving
> issue
sure, thx for pointing this out.
@Deren: can you please double check?
Regards,
Lorenzo
>
> > >
> > > I'm thinking if it's too early to create this patch for just moving
> > > mt7996 to connac3_lib?
> >
> > The code I moved is used by the other device as well. This series is
> > a
> > preliminary series to support it.
> >
> > Regards,
> > Lorenzo
> >
> > >
> > > Ryder
> > >
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread[parent not found: <PH8PR12MB7230DC95457EF9C667E679AEAC51A@PH8PR12MB7230.namprd12.prod.outlook.com>]
* Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library
2023-06-09 16:45 ` lorenzo
[not found] ` <PH8PR12MB7230DC95457EF9C667E679AEAC51A@PH8PR12MB7230.namprd12.prod.outlook.com>
@ 2023-06-10 2:22 ` Deren Wu (武德仁)
2023-06-10 7:49 ` lorenzo
1 sibling, 1 reply; 27+ messages in thread
From: Deren Wu (武德仁) @ 2023-06-10 2:22 UTC (permalink / raw)
To: Shayne Chen (陳軒丞), lorenzo@kernel.org,
Ryder Lee
Cc: lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org,
nbd@nbd.name
On Fri, 2023-06-09 at 18:45 +0200, lorenzo@kernel.org wrote:
> > On Fri, 2023-06-09 at 18:34 +0200, lorenzo.bianconi@redhat.com
> > wrote:
> > > On Jun 09, Ryder Lee wrote:
> > > > On Fri, 2023-06-09 at 10:15 +0200, Lorenzo Bianconi wrote:
> > > > >
> > > > > External email : Please do not click links or open
> > > > > attachments
> > > > > until
> > > > > you have verified the sender or the content.
> > > > > Introduce connac3_mac in mt76_connac library to reuse mac
> > > > > code
> > > > > shared
> > > > > between WiFi7 chipsets.
> > > > >
> > > > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > > ---
> > > > > drivers/net/wireless/mediatek/mt76/Makefile | 2 +-
> > > > > .../net/wireless/mediatek/mt76/mt76_connac.h | 19 +
> > > > > .../wireless/mediatek/mt76/mt76_connac3_mac.c | 742
> > > > > +++++++++++++++++
> > > > > .../wireless/mediatek/mt76/mt76_connac3_mac.h | 18 +
> > > > > .../net/wireless/mediatek/mt76/mt7996/init.c | 4 +-
> > > > > .../net/wireless/mediatek/mt76/mt7996/mac.c | 761 +-------
> > > > > ----
> > > > > ----
> > > > > --
> > > > > .../net/wireless/mediatek/mt76/mt7996/main.c | 8 +-
> > > > > .../net/wireless/mediatek/mt76/mt7996/mcu.c | 9 +-
> > > > > .../wireless/mediatek/mt76/mt7996/mt7996.h | 28 +-
> > > > > 9 files changed, 807 insertions(+), 784 deletions(-)
> > > > > create mode 100644
> > > > > drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > > >
> > > > > diff --git a/drivers/net/wireless/mediatek/mt76/Makefile
> > > > > b/drivers/net/wireless/mediatek/mt76/Makefile
> > > > > index 84c99b7e57f9..d8e8079c8b54 100644
> > > > > --- a/drivers/net/wireless/mediatek/mt76/Makefile
> > > > > +++ b/drivers/net/wireless/mediatek/mt76/Makefile
> > > > > @@ -27,7 +27,7 @@ mt76x02-lib-y := mt76x02_util.o
> > > > > mt76x02_mac.o
> > > > > mt76x02_mcu.o \
> > > > >
> > > > > mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
> > > > >
> > > > > -mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
> > > > > +mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
> > > > > mt76_connac3_mac.o
> > > > >
> > > > > obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
> > > > > obj-$(CONFIG_MT76x2_COMMON) += mt76x2/
> > > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > > > b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > > > index 68bdeada1421..20111678537b 100644
> > > > > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > > > @@ -415,4 +415,23 @@ void mt76_connac2_txwi_free(struct
> > > > > mt76_dev
> > > > > *dev, struct mt76_txwi_cache *t,
> > > > > struct list_head *free_list);
> > > > > void mt76_connac2_tx_token_put(struct mt76_dev *dev);
> > > > >
> > > > > +/* connac3 */
> > > > > +void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta,
> > > > > __le32
> > > > > *txwi);
> > > > > +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff
> > > > > *skb,
> > > > > __le32
> > > > > *rxv,
> > > > > + u8 mode);
> > > > > +int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev,
> > > > > + struct mt76_rx_status
> > > > > *status,
> > > > > + struct
> > > > > ieee80211_supported_band
> > > > > *sband,
> > > > > + __le32 *rxv, u8 *mode);
> > > > > +void mt76_connac3_mac_write_txwi(struct mt76_dev *dev,
> > > > > __le32
> > > > > *txwi,
> > > > > + struct sk_buff *skb, struct
> > > > > mt76_wcid
> > > > > *wcid,
> > > > > + struct ieee80211_key_conf
> > > > > *key, int
> > > > > pid,
> > > > > + enum mt76_txq_id qid, u32
> > > > > changed);
> > > > > +void mt76_connac3_txwi_free(struct mt76_dev *dev, struct
> > > > > mt76_txwi_cache *t,
> > > > > + struct ieee80211_sta *sta,
> > > > > + struct list_head *free_list);
> > > > > +void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void
> > > > > *data,
> > > > > + u32 max_wtbl_size);
> > > > > +void mt76_connac3_tx_token_put(struct mt76_dev *dev);
> > > > > +
> > > > > #endif /* __MT76_CONNAC_H */
> > > > > diff --git
> > > > > a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > > > b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > > > new file mode 100644
> > > > > index 000000000000..4b745bb74ca0
> > > > > --- /dev/null
> > > > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > > > @@ -0,0 +1,742 @@
> > > > > +// SPDX-License-Identifier: ISC
> > > > > +/* Copyright (C) 2023 MediaTek Inc. */
> > > > > +
> > > > > +#include "mt76_connac.h"
> > > > > +#include "mt76_connac3_mac.h"
> > > > > +#include "dma.h"
> > > > > +
> > > > > +#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_
> > > > > HE_##f)
> > > > > +#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(
> > > > > v,
> > > > > MT_CRXV_HE_##m),\
> > > > > + IEEE80211_RADI
> > > > > OTAP_HE_
> > > > > ##f)
> > > > > +
> > > > > +void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta,
> > > > > __le32
> > > > > *txwi)
> > > > > +{
> > > > > + struct mt76_wcid *wcid;
> > > > > + u16 fc, tid;
> > > > > + u32 val;
> > > > > +
> > > > > + if (!sta ||
> > > > > + !(sta->deflink.ht_cap.ht_supported || sta-
> > > > > > deflink.he_cap.has_he))
> > > > >
> > > > > + return;
> > > > > +
> > > > > + tid = le32_get_bits(txwi[1], MT_TXD1_TID);
> > > > > + if (tid >= 6) /* skip VO queue */
> > > > > + return;
> > > > > +
> > > > > + val = le32_to_cpu(txwi[2]);
> > > > > + fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
> > > > > + FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
> > > > > + if (unlikely(fc != (IEEE80211_FTYPE_DATA |
> > > > > IEEE80211_STYPE_QOS_DATA)))
> > > > > + return;
> > > > > +
> > > > > + wcid = (struct mt76_wcid *)sta->drv_priv;
> > > > > + if (!test_and_set_bit(tid, &wcid->ampdu_state))
> > > > > + ieee80211_start_tx_ba_session(sta, tid, 0);
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(mt76_connac3_tx_check_aggr);
> > > > > +
> > > > > +static void
> > > > > +mt76_connac3_mac_decode_he_radiotap_ru(struct mt76_rx_status
> > > > > *status,
> > > > > + struct
> > > > > ieee80211_radiotap_he
> > > > > *he,
> > > > > + __le32 *rxv)
> > > > > +{
> > > > > + u32 ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC),
> > > > > offs = 0;
> > > > > +
> > > > > + status->bw = RATE_INFO_BW_HE_RU;
> > > > > +
> > > > > + switch (ru) {
> > > > > + case 0 ... 36:
> > > > > + status->he_ru =
> > > > > NL80211_RATE_INFO_HE_RU_ALLOC_26;
> > > > > + offs = ru;
> > > > > + break;
> > > > > + case 37 ... 52:
> > > > > + status->he_ru =
> > > > > NL80211_RATE_INFO_HE_RU_ALLOC_52;
> > > > > + offs = ru - 37;
> > > > > + break;
> > > > > + case 53 ... 60:
> > > > > + status->he_ru =
> > > > > NL80211_RATE_INFO_HE_RU_ALLOC_106;
> > > > > + offs = ru - 53;
> > > > > + break;
> > > > > + case 61 ... 64:
> > > > > + status->he_ru =
> > > > > NL80211_RATE_INFO_HE_RU_ALLOC_242;
> > > > > + offs = ru - 61;
> > > > > + break;
> > > > > + case 65 ... 66:
> > > > > + status->he_ru =
> > > > > NL80211_RATE_INFO_HE_RU_ALLOC_484;
> > > > > + offs = ru - 65;
> > > > > + break;
> > > > > + case 67:
> > > > > + status->he_ru =
> > > > > NL80211_RATE_INFO_HE_RU_ALLOC_996;
> > > > > + break;
> > > > > + case 68:
> > > > > + status->he_ru =
> > > > > NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
> > > > > + break;
> > > > > + }
> > > > > +
> > > > > + he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > > > > + he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
> > > > > + le16_encode_bits(offs,
> > > > > + IEEE80211_RADIOTAP_HE_DAT
> > > > > A2_RU_OF
> > > > > FSET);
> > > > > +}
> > > > > +
> > > > > +#define MU_PREP(f, v) le16_encode_bits(v,
> > > > > IEEE80211_RADIOTAP_HE_MU_##f)
> > > > > +static void
> > > > > +mt76_connac3_mac_decode_he_mu_radiotap(struct sk_buff *skb,
> > > > > __le32
> > > > > *rxv)
> > > > > +{
> > > > > + struct mt76_rx_status *status = (struct mt76_rx_status
> > > > > *)skb-
> > > > > > cb;
> > > > >
> > > > > + static const struct ieee80211_radiotap_he_mu mu_known =
> > > > > {
> > > > > + .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
> > > > > + HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
> > > > > + HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
> > > > > + HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KN
> > > > > OWN),
> > > > > + .flags2 =
> > > > > HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
> > > > > + };
> > > > > + struct ieee80211_radiotap_he_mu *he_mu;
> > > > > +
> > > > > + status->flag |= RX_FLAG_RADIOTAP_HE_MU;
> > > > > +
> > > > > + he_mu = skb_push(skb, sizeof(mu_known));
> > > > > + memcpy(he_mu, &mu_known, sizeof(mu_known));
> > > > > +
> > > > > + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status-
> > > > > >rate_idx);
> > > > > + if (status->he_dcm)
> > > > > + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM,
> > > > > status-
> > > > > > he_dcm);
> > > > >
> > > > > +
> > > > > + he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW,
> > > > > status->bw) |
> > > > > + MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
> > > > > + le32_get_bits(rxv[4],
> > > > > MT_CRXV_HE_NUM_USER));
> > > > > +
> > > > > + he_mu->ru_ch1[0] = le32_get_bits(rxv[16],
> > > > > MT_CRXV_HE_RU0) &
> > > > > 0xff;
> > > > > +
> > > > > + if (status->bw >= RATE_INFO_BW_40) {
> > > > > + he_mu->flags1 |=
> > > > > HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
> > > > > + he_mu->ru_ch2[0] = le32_get_bits(rxv[16],
> > > > > MT_CRXV_HE_RU1) & 0xff;
> > > > > + }
> > > > > +
> > > > > + if (status->bw >= RATE_INFO_BW_80) {
> > > > > + u32 ru_h, ru_l;
> > > > > +
> > > > > + he_mu->ru_ch1[1] = le32_get_bits(rxv[16],
> > > > > MT_CRXV_HE_RU2) & 0xff;
> > > > > +
> > > > > + ru_l = le32_get_bits(rxv[16],
> > > > > MT_CRXV_HE_RU3_L);
> > > > > + ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H)
> > > > > & 0x7;
> > > > > + he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4);
> > > > > + }
> > > > > +}
> > > > > +
> > > > > +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff
> > > > > *skb,
> > > > > __le32
> > > > > *rxv,
> > > > > + u8 mode)
> > > > > +{
> > > > > + struct mt76_rx_status *status = (struct mt76_rx_status
> > > > > *)skb-
> > > > > > cb;
> > > > >
> > > > > + static const struct ieee80211_radiotap_he known = {
> > > > > + .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
> > > > > + HE_BITS(DATA1_DATA_DCM_KNOWN) |
> > > > > + HE_BITS(DATA1_STBC_KNOWN) |
> > > > > + HE_BITS(DATA1_CODING_KNOWN) |
> > > > > + HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
> > > > > + HE_BITS(DATA1_DOPPLER_KNOWN) |
> > > > > + HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
> > > > > + HE_BITS(DATA1_BSS_COLOR_KNOWN),
> > > > > + .data2 = HE_BITS(DATA2_GI_KNOWN) |
> > > > > + HE_BITS(DATA2_TXBF_KNOWN) |
> > > > > + HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
> > > > > + HE_BITS(DATA2_TXOP_KNOWN),
> > > > > + };
> > > > > + u32 ltf_size = le32_get_bits(rxv[4],
> > > > > MT_CRXV_HE_LTF_SIZE) + 1;
> > > > > + struct ieee80211_radiotap_he *he;
> > > > > +
> > > > > + status->flag |= RX_FLAG_RADIOTAP_HE;
> > > > > +
> > > > > + he = skb_push(skb, sizeof(known));
> > > > > + memcpy(he, &known, sizeof(known));
> > > > > +
> > > > > + he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9])
> > > > > |
> > > > > + HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM,
> > > > > rxv[4]);
> > > > > + he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK,
> > > > > rxv[13]);
> > > > > + he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG,
> > > > > rxv[5]) |
> > > > > + le16_encode_bits(ltf_size,
> > > > > + IEEE80211_RADIOTAP_HE_DATA
> > > > > 5_LTF_SI
> > > > > ZE);
> > > > > + if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
> > > > > + he->data5 |= HE_BITS(DATA5_TXBF);
> > > > > + he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) |
> > > > > + HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]);
> > > > > +
> > > > > + switch (mode) {
> > > > > + case MT_PHY_TYPE_HE_SU:
> > > > > + he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
> > > > > + HE_BITS(DATA1_UL_DL_KNOWN) |
> > > > > + HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
> > > > > + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > > > > +
> > > > > + he->data3 |= HE_PREP(DATA3_BEAM_CHANGE,
> > > > > BEAM_CHNG,
> > > > > rxv[8]) |
> > > > > + HE_PREP(DATA3_UL_DL, UPLINK,
> > > > > rxv[5]);
> > > > > + break;
> > > > > + case MT_PHY_TYPE_HE_EXT_SU:
> > > > > + he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
> > > > > + HE_BITS(DATA1_UL_DL_KNOWN) |
> > > > > + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > > > > +
> > > > > + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK,
> > > > > rxv[5]);
> > > > > + break;
> > > > > + case MT_PHY_TYPE_HE_MU:
> > > > > + he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
> > > > > + HE_BITS(DATA1_UL_DL_KNOWN);
> > > > > +
> > > > > + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK,
> > > > > rxv[5]);
> > > > > + he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID,
> > > > > rxv[8]);
> > > > > +
> > > > > + mt76_connac3_mac_decode_he_radiotap_ru(status,
> > > > > he,
> > > > > rxv);
> > > > > + mt76_connac3_mac_decode_he_mu_radiotap(skb,
> > > > > rxv);
> > > > > + break;
> > > > > + case MT_PHY_TYPE_HE_TB:
> > > > > + he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
> > > > > + HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
> > > > > + HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
> > > > > + HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
> > > > > +
> > > > > + he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1,
> > > > > SR_MASK,
> > > > > rxv[13]) |
> > > > > + HE_PREP(DATA4_TB_SPTL_REUSE2,
> > > > > SR1_MASK,
> > > > > rxv[13]) |
> > > > > + HE_PREP(DATA4_TB_SPTL_REUSE3,
> > > > > SR2_MASK,
> > > > > rxv[13]) |
> > > > > + HE_PREP(DATA4_TB_SPTL_REUSE4,
> > > > > SR3_MASK,
> > > > > rxv[13]);
> > > > > +
> > > > > + mt76_connac3_mac_decode_he_radiotap_ru(status,
> > > > > he,
> > > > > rxv);
> > > > > + break;
> > > > > + default:
> > > > > + break;
> > > > > + }
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap);
> > > > > +
> > > > > +int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev,
> > > > > + struct mt76_rx_status
> > > > > *status,
> > > > > + struct
> > > > > ieee80211_supported_band
> > > > > *sband,
> > > > > + __le32 *rxv, u8 *mode)
> > > > > +{
> > > > > + u8 stbc, gi, bw, dcm, nss;
> > > > > + bool cck = false;
> > > > > + u32 v0, v2;
> > > > > + int i, idx;
> > > > > +
> > > > > + v0 = le32_to_cpu(rxv[0]);
> > > > > + v2 = le32_to_cpu(rxv[2]);
> > > > > +
> > > > > + idx = FIELD_GET(MT_PRXV_TX_RATE, v0);
> > > > > + i = idx;
> > > > > + nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1;
> > > > > +
> > > > > + stbc = FIELD_GET(MT_PRXV_HT_STBC, v2);
> > > > > + gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2);
> > > > > + *mode = FIELD_GET(MT_PRXV_TX_MODE, v2);
> > > > > + dcm = FIELD_GET(MT_PRXV_DCM, v2);
> > > > > + bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2);
> > > > > +
> > > > > + switch (*mode) {
> > > > > + case MT_PHY_TYPE_CCK:
> > > > > + cck = true;
> > > > > + fallthrough;
> > > > > + case MT_PHY_TYPE_OFDM:
> > > > > + i = mt76_get_rate(dev, sband, i, cck);
> > > > > + break;
> > > > > + case MT_PHY_TYPE_HT_GF:
> > > > > + case MT_PHY_TYPE_HT:
> > > > > + status->encoding = RX_ENC_HT;
> > > > > + if (gi)
> > > > > + status->enc_flags |=
> > > > > RX_ENC_FLAG_SHORT_GI;
> > > > > + if (i > 31)
> > > > > + return -EINVAL;
> > > > > + break;
> > > > > + case MT_PHY_TYPE_VHT:
> > > > > + status->nss = nss;
> > > > > + status->encoding = RX_ENC_VHT;
> > > > > + if (gi)
> > > > > + status->enc_flags |=
> > > > > RX_ENC_FLAG_SHORT_GI;
> > > > > + if (i > 11)
> > > > > + return -EINVAL;
> > > > > + break;
> > > > > + case MT_PHY_TYPE_HE_MU:
> > > > > + case MT_PHY_TYPE_HE_SU:
> > > > > + case MT_PHY_TYPE_HE_EXT_SU:
> > > > > + case MT_PHY_TYPE_HE_TB:
> > > > > + status->nss = nss;
> > > > > + status->encoding = RX_ENC_HE;
> > > > > + i &= GENMASK(3, 0);
> > > > > +
> > > > > + if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
> > > > > + status->he_gi = gi;
> > > > > +
> > > > > + status->he_dcm = dcm;
> > > > > + break;
> > > > > + case MT_PHY_TYPE_EHT_SU:
> > > > > + case MT_PHY_TYPE_EHT_TRIG:
> > > > > + case MT_PHY_TYPE_EHT_MU:
> > > > > + status->nss = nss;
> > > > > + status->encoding = RX_ENC_EHT;
> > > > > + i &= GENMASK(3, 0);
> > > > > +
> > > > > + if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
> > > > > + status->eht.gi = gi;
> > > > > + break;
> > > > > + default:
> > > > > + return -EINVAL;
> > > > > + }
> > > > > + status->rate_idx = i;
> > > > > +
> > > > > + switch (bw) {
> > > > > + case IEEE80211_STA_RX_BW_20:
> > > > > + break;
> > > > > + case IEEE80211_STA_RX_BW_40:
> > > > > + if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
> > > > > + (idx & MT_PRXV_TX_ER_SU_106T)) {
> > > > > + status->bw = RATE_INFO_BW_HE_RU;
> > > > > + status->he_ru =
> > > > > + NL80211_RATE_INFO_HE_RU_ALLOC_1
> > > > > 06;
> > > > > + } else {
> > > > > + status->bw = RATE_INFO_BW_40;
> > > > > + }
> > > > > + break;
> > > > > + case IEEE80211_STA_RX_BW_80:
> > > > > + status->bw = RATE_INFO_BW_80;
> > > > > + break;
> > > > > + case IEEE80211_STA_RX_BW_160:
> > > > > + status->bw = RATE_INFO_BW_160;
> > > > > + break;
> > > > > + case IEEE80211_STA_RX_BW_320:
> > > > > + status->bw = RATE_INFO_BW_320;
> > > > > + break;
> > > > > + default:
> > > > > + return -EINVAL;
> > > > > + }
> > > > > +
> > > > > + status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
> > > > > + if (*mode < MT_PHY_TYPE_HE_SU && gi)
> > > > > + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
> > > > > +
> > > > > + return 0;
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_fill_rx_rate);
> > > > > +
> > > > > +static void
> > > > > +mt76_connac3_mac_write_txwi_8023(__le32 *txwi, struct
> > > > > sk_buff
> > > > > *skb,
> > > > > + struct mt76_wcid *wcid)
> > > > > +{
> > > > > + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
> > > > > + u8 fc_type, fc_stype;
> > > > > + u16 ethertype;
> > > > > + bool wmm = false;
> > > > > + u32 val;
> > > > > +
> > > > > + if (wcid->sta) {
> > > > > + struct ieee80211_sta *sta;
> > > > > +
> > > > > + sta = container_of((void *)wcid, struct
> > > > > ieee80211_sta,
> > > > > drv_priv);
> > > > > + wmm = sta->wme;
> > > > > + }
> > > > > +
> > > > > + val = FIELD_PREP(MT_TXD1_HDR_FORMAT,
> > > > > MT_HDR_FORMAT_802_3) |
> > > > > + FIELD_PREP(MT_TXD1_TID, tid);
> > > > > +
> > > > > + ethertype = get_unaligned_be16(&skb->data[12]);
> > > > > + if (ethertype >= ETH_P_802_3_MIN)
> > > > > + val |= MT_TXD1_ETH_802_3;
> > > > > +
> > > > > + txwi[1] |= cpu_to_le32(val);
> > > > > +
> > > > > + fc_type = IEEE80211_FTYPE_DATA >> 2;
> > > > > + fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0;
> > > > > +
> > > > > + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
> > > > > + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
> > > > > +
> > > > > + txwi[2] |= cpu_to_le32(val);
> > > > > +}
> > > > > +
> > > > > +static void
> > > > > +mt76_connac3_mac_write_txwi_80211(struct mt76_dev *dev,
> > > > > __le32
> > > > > *txwi,
> > > > > + struct sk_buff *skb,
> > > > > + struct ieee80211_key_conf
> > > > > *key)
> > > > > +{
> > > > > + struct ieee80211_hdr *hdr = (struct ieee80211_hdr
> > > > > *)skb->data;
> > > > > + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt
> > > > > *)skb-
> > > > > > data;
> > > > >
> > > > > + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> > > > > + bool multicast = is_multicast_ether_addr(hdr->addr1);
> > > > > + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
> > > > > + __le16 fc = hdr->frame_control;
> > > > > + u8 fc_type, fc_stype;
> > > > > + u32 val;
> > > > > +
> > > > > + if (ieee80211_is_action(fc) &&
> > > > > + mgmt->u.action.category == WLAN_CATEGORY_BACK &&
> > > > > + mgmt->u.action.u.addba_req.action_code ==
> > > > > WLAN_ACTION_ADDBA_REQ)
> > > > > + tid = MT_TX_ADDBA;
> > > > > + else if (ieee80211_is_mgmt(hdr->frame_control))
> > > > > + tid = MT_TX_NORMAL;
> > > > > +
> > > > > + val = FIELD_PREP(MT_TXD1_HDR_FORMAT,
> > > > > MT_HDR_FORMAT_802_11) |
> > > > > + FIELD_PREP(MT_TXD1_HDR_INFO,
> > > > > + ieee80211_get_hdrlen_from_skb(skb) /
> > > > > 2) |
> > > > > + FIELD_PREP(MT_TXD1_TID, tid);
> > > > > +
> > > > > + if (!ieee80211_is_data(fc) || multicast ||
> > > > > + info->flags & IEEE80211_TX_CTL_USE_MINRATE)
> > > > > + val |= MT_TXD1_FIXED_RATE;
> > > > > +
> > > > > + if (key && multicast &&
> > > > > ieee80211_is_robust_mgmt_frame(skb) &&
> > > > > + key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
> > > > > + val |= MT_TXD1_BIP;
> > > > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
> > > > > + }
> > > > > +
> > > > > + txwi[1] |= cpu_to_le32(val);
> > > > > +
> > > > > + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >>
> > > > > 2;
> > > > > + fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >>
> > > > > 4;
> > > > > +
> > > > > + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
> > > > > + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
> > > > > +
> > > > > + txwi[2] |= cpu_to_le32(val);
> > > > > +
> > > > > + txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM,
> > > > > multicast));
> > > > > + if (ieee80211_is_beacon(fc)) {
> > > > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT);
> > > > > + txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
> > > > > + }
> > > > > +
> > > > > + if (info->flags & IEEE80211_TX_CTL_INJECTED) {
> > > > > + u16 seqno = le16_to_cpu(hdr->seq_ctrl);
> > > > > +
> > > > > + if (ieee80211_is_back_req(hdr->frame_control))
> > > > > {
> > > > > + struct ieee80211_bar *bar;
> > > > > +
> > > > > + bar = (struct ieee80211_bar *)skb-
> > > > > >data;
> > > > > + seqno = le16_to_cpu(bar-
> > > > > >start_seq_num);
> > > > > + }
> > > > > +
> > > > > + val = MT_TXD3_SN_VALID |
> > > > > + FIELD_PREP(MT_TXD3_SEQ,
> > > > > IEEE80211_SEQ_TO_SN(seqno));
> > > > > + txwi[3] |= cpu_to_le32(val);
> > > > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
> > > > > + }
> > > > > +}
> > > > > +
> > > > > +void mt76_connac3_mac_write_txwi(struct mt76_dev *dev,
> > > > > __le32
> > > > > *txwi,
> > > > > + struct sk_buff *skb, struct
> > > > > mt76_wcid
> > > > > *wcid,
> > > > > + struct ieee80211_key_conf
> > > > > *key, int
> > > > > pid,
> > > > > + enum mt76_txq_id qid, u32
> > > > > changed)
> > > > > +{
> > > > > + u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE :
> > > > > MT_SDIO_TXD_SIZE;
> > > > > + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> > > > > + struct ieee80211_vif *vif = info->control.vif;
> > > > > + u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >>
> > > > > 2;
> > > > > + u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
> > > > > + bool is_8023 = info->flags &
> > > > > IEEE80211_TX_CTL_HW_80211_ENCAP;
> > > > > + struct mt76_vif *mvif;
> > > > > + u16 tx_count = 15;
> > > > > + bool beacon = !!(changed & (BSS_CHANGED_BEACON |
> > > > > + BSS_CHANGED_BEACON_ENABLED)
> > > > > );
> > > > > + bool inband_disc = !!(changed &
> > > > > (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
> > > > > + BSS_CHANGED_FILS_DISCO
> > > > > VERY));
> > > > > +
> > > > > + mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL;
> > > > > + if (mvif) {
> > > > > + omac_idx = mvif->omac_idx;
> > > > > + wmm_idx = mvif->wmm_idx;
> > > > > + band_idx = mvif->band_idx;
> > > > > + }
> > > > > +
> > > > > + if (inband_disc) {
> > > > > + p_fmt = MT_TX_TYPE_FW;
> > > > > + q_idx = MT_LMAC_ALTX0;
> > > > > + } else if (beacon) {
> > > > > + p_fmt = MT_TX_TYPE_FW;
> > > > > + q_idx = MT_LMAC_BCN0;
> > > > > + } else if (qid >= MT_TXQ_PSD) {
> > > > > + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT :
> > > > > MT_TX_TYPE_SF;
> > > > > + q_idx = MT_LMAC_ALTX0;
> > > > > + } else {
> > > > > + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT :
> > > > > MT_TX_TYPE_SF;
> > > > > + q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS +
> > > > > + mt76_connac_lmac_mapping(skb_get_queue_
> > > > > mapping(
> > > > > skb));
> > > > > + }
> > > > > +
> > > > > + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
> > > > > + FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
> > > > > + FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
> > > > > + txwi[0] = cpu_to_le32(val);
> > > > > +
> > > > > + val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
> > > > > + FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
> > > > > +
> > > > > + if (band_idx)
> > > > > + val |= FIELD_PREP(MT_TXD1_TGID, band_idx);
> > > > > +
> > > > > + txwi[1] = cpu_to_le32(val);
> > > > > + txwi[2] = 0;
> > > > > +
> > > > > + val = MT_TXD3_SW_POWER_MGMT |
> > > > > + FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count);
> > > > > + if (key)
> > > > > + val |= MT_TXD3_PROTECT_FRAME;
> > > > > + if (info->flags & IEEE80211_TX_CTL_NO_ACK)
> > > > > + val |= MT_TXD3_NO_ACK;
> > > > > + if (wcid->amsdu)
> > > > > + val |= MT_TXD3_HW_AMSDU;
> > > > > +
> > > > > + txwi[3] = cpu_to_le32(val);
> > > > > + txwi[4] = 0;
> > > > > +
> > > > > + val = FIELD_PREP(MT_TXD5_PID, pid);
> > > > > + if (pid >= MT_PACKET_ID_FIRST)
> > > > > + val |= MT_TXD5_TX_STATUS_HOST;
> > > > > + txwi[5] = cpu_to_le32(val);
> > > > > +
> > > > > + val = MT_TXD6_DIS_MAT | MT_TXD6_DAS |
> > > > > + FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
> > > > > + txwi[6] = cpu_to_le32(val);
> > > > > + txwi[7] = 0;
> > > > > +
> > > > > + if (is_8023)
> > > > > + mt76_connac3_mac_write_txwi_8023(txwi, skb,
> > > > > wcid);
> > > > > + else
> > > > > + mt76_connac3_mac_write_txwi_80211(dev, txwi,
> > > > > skb, key);
> > > > > +
> > > > > + if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
> > > > > + struct ieee80211_hdr *hdr = (struct
> > > > > ieee80211_hdr
> > > > > *)skb->data;
> > > > > + bool mcast = ieee80211_is_data(hdr-
> > > > > >frame_control) &&
> > > > > + is_multicast_ether_addr(hdr-
> > > > > >addr1);
> > > > > + u8 idx = MT76_CONNAC3_BASIC_RATES_TBL;
> > > > > +
> > > > > + if (mvif) {
> > > > > + if (mcast && mvif->mcast_rates_idx)
> > > > > + idx = mvif->mcast_rates_idx;
> > > > > + else if (beacon && mvif-
> > > > > >beacon_rates_idx)
> > > > > + idx = mvif->beacon_rates_idx;
> > > > > + else
> > > > > + idx = mvif->basic_rates_idx;
> > > > > + }
> > > > > +
> > > > > + txwi[6] |=
> > > > > cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE,
> > > > > idx));
> > > > > + txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
> > > > > + }
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_write_txwi);
> > > > > +
> > > > > +void mt76_connac3_txwi_free(struct mt76_dev *dev, struct
> > > > > mt76_txwi_cache *t,
> > > > > + struct ieee80211_sta *sta,
> > > > > + struct list_head *free_list)
> > > > > +{
> > > > > + __le32 *txwi;
> > > > > + u16 wcid_idx;
> > > > > +
> > > > > + mt76_connac_txp_skb_unmap(dev, t);
> > > > > + if (!t->skb)
> > > > > + goto out;
> > > > > +
> > > > > + txwi = (__le32 *)mt76_get_txwi_ptr(dev, t);
> > > > > + if (sta) {
> > > > > + struct mt76_wcid *wcid = (struct mt76_wcid
> > > > > *)sta-
> > > > > > drv_priv;
> > > > >
> > > > > +
> > > > > + wcid_idx = wcid->idx;
> > > > > + if (likely(t->skb->protocol !=
> > > > > cpu_to_be16(ETH_P_PAE)))
> > > > > + mt76_connac3_tx_check_aggr(sta, txwi);
> > > > > + } else {
> > > > > + wcid_idx = le32_get_bits(txwi[1],
> > > > > MT_TXD1_WLAN_IDX);
> > > > > + }
> > > > > +
> > > > > + __mt76_tx_complete_skb(dev, wcid_idx, t->skb,
> > > > > free_list);
> > > > > +out:
> > > > > + t->skb = NULL;
> > > > > + mt76_put_txwi(dev, t);
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(mt76_connac3_txwi_free);
> > > > > +
> > > > > +static bool
> > > > > +mt76_connac3_mac_add_txs_skb(struct mt76_dev *dev, struct
> > > > > mt76_wcid
> > > > > *wcid,
> > > > > + int pid, __le32 *txs_data)
> > > > > +{
> > > > > + struct mt76_sta_stats *stats = &wcid->stats;
> > > > > + struct ieee80211_supported_band *sband;
> > > > > + struct ieee80211_tx_info *info;
> > > > > + u32 txrate, txs, mode, stbc;
> > > > > + struct rate_info rate = {};
> > > > > + struct sk_buff_head list;
> > > > > + struct mt76_phy *mphy;
> > > > > + struct sk_buff *skb;
> > > > > + bool cck = false;
> > > > > +
> > > > > + mt76_tx_status_lock(dev, &list);
> > > > > + skb = mt76_tx_status_skb_get(dev, wcid, pid, &list);
> > > > > + if (!skb)
> > > > > + goto out_no_skb;
> > > > > +
> > > > > + txs = le32_to_cpu(txs_data[0]);
> > > > > +
> > > > > + info = IEEE80211_SKB_CB(skb);
> > > > > + if (!(txs & MT_TXS0_ACK_ERROR_MASK))
> > > > > + info->flags |= IEEE80211_TX_STAT_ACK;
> > > > > +
> > > > > + info->status.ampdu_len = 1;
> > > > > + info->status.ampdu_ack_len = !!(info->flags &
> > > > > + IEEE80211_TX_STAT_ACK);
> > > > > + info->status.rates[0].idx = -1;
> > > > > +
> > > > > + txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
> > > > > +
> > > > > + rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
> > > > > + rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
> > > > > + stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC);
> > > > > +
> > > > > + if (stbc && rate.nss > 1)
> > > > > + rate.nss >>= 1;
> > > > > +
> > > > > + if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
> > > > > + stats->tx_nss[rate.nss - 1]++;
> > > > > + if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
> > > > > + stats->tx_mcs[rate.mcs]++;
> > > > > +
> > > > > + mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
> > > > > + switch (mode) {
> > > > > + case MT_PHY_TYPE_CCK:
> > > > > + cck = true;
> > > > > + fallthrough;
> > > > > + case MT_PHY_TYPE_OFDM:
> > > > > + mphy = mt76_dev_phy(dev, wcid->phy_idx);
> > > > > +
> > > > > + if (mphy->chandef.chan->band ==
> > > > > NL80211_BAND_5GHZ)
> > > > > + sband = &mphy->sband_5g.sband;
> > > > > + else if (mphy->chandef.chan->band ==
> > > > > NL80211_BAND_6GHZ)
> > > > > + sband = &mphy->sband_6g.sband;
> > > > > + else
> > > > > + sband = &mphy->sband_2g.sband;
> > > > > +
> > > > > + rate.mcs = mt76_get_rate(mphy->dev, sband,
> > > > > rate.mcs,
> > > > > cck);
> > > > > + rate.legacy = sband-
> > > > > >bitrates[rate.mcs].bitrate;
> > > > > + break;
> > > > > + case MT_PHY_TYPE_HT:
> > > > > + case MT_PHY_TYPE_HT_GF:
> > > > > + if (rate.mcs > 31)
> > > > > + goto out;
> > > > > +
> > > > > + rate.flags = RATE_INFO_FLAGS_MCS;
> > > > > + if (wcid->rate.flags &
> > > > > RATE_INFO_FLAGS_SHORT_GI)
> > > > > + rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
> > > > > + break;
> > > > > + case MT_PHY_TYPE_VHT:
> > > > > + if (rate.mcs > 9)
> > > > > + goto out;
> > > > > +
> > > > > + rate.flags = RATE_INFO_FLAGS_VHT_MCS;
> > > > > + break;
> > > > > + case MT_PHY_TYPE_HE_SU:
> > > > > + case MT_PHY_TYPE_HE_EXT_SU:
> > > > > + case MT_PHY_TYPE_HE_TB:
> > > > > + case MT_PHY_TYPE_HE_MU:
> > > > > + if (rate.mcs > 11)
> > > > > + goto out;
> > > > > +
> > > > > + rate.he_gi = wcid->rate.he_gi;
> > > > > + rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM,
> > > > > txrate);
> > > > > + rate.flags = RATE_INFO_FLAGS_HE_MCS;
> > > > > + break;
> > > > > + case MT_PHY_TYPE_EHT_SU:
> > > > > + case MT_PHY_TYPE_EHT_TRIG:
> > > > > + case MT_PHY_TYPE_EHT_MU:
> > > > > + if (rate.mcs > 13)
> > > > > + goto out;
> > > > > +
> > > > > + rate.eht_gi = wcid->rate.eht_gi;
> > > > > + rate.flags = RATE_INFO_FLAGS_EHT_MCS;
> > > > > + break;
> > > > > + default:
> > > > > + goto out;
> > > > > + }
> > > > > +
> > > > > + stats->tx_mode[mode]++;
> > > > > +
> > > > > + switch (FIELD_GET(MT_TXS0_BW, txs)) {
> > > > > + case IEEE80211_STA_RX_BW_320:
> > > > > + rate.bw = RATE_INFO_BW_320;
> > > > > + stats->tx_bw[4]++;
> > > > > + break;
> > > > > + case IEEE80211_STA_RX_BW_160:
> > > > > + rate.bw = RATE_INFO_BW_160;
> > > > > + stats->tx_bw[3]++;
> > > > > + break;
> > > > > + case IEEE80211_STA_RX_BW_80:
> > > > > + rate.bw = RATE_INFO_BW_80;
> > > > > + stats->tx_bw[2]++;
> > > > > + break;
> > > > > + case IEEE80211_STA_RX_BW_40:
> > > > > + rate.bw = RATE_INFO_BW_40;
> > > > > + stats->tx_bw[1]++;
> > > > > + break;
> > > > > + default:
> > > > > + rate.bw = RATE_INFO_BW_20;
> > > > > + stats->tx_bw[0]++;
> > > > > + break;
> > > > > + }
> > > > > + wcid->rate = rate;
> > > > > +
> > > > > +out:
> > > > > + mt76_tx_status_skb_done(dev, skb, &list);
> > > > > +
> > > > > +out_no_skb:
> > > > > + mt76_tx_status_unlock(dev, &list);
> > > > > +
> > > > > + return !!skb;
> > > > > +}
> > > > > +
> > > > > +void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void
> > > > > *data,
> > > > > + u32 max_wtbl_size)
> > > > > +{
> > > > > + struct mt76_wcid *wcid;
> > > > > + __le32 *txs_data = data;
> > > > > + u16 wcidx;
> > > > > + u8 pid;
> > > > > +
> > > > > + if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
> > > > > + return;
> > > > > +
> > > > > + wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
> > > > > + pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
> > > > > +
> > > > > + if (pid < MT_PACKET_ID_FIRST)
> > > > > + return;
> > > > > +
> > > > > + if (wcidx >= max_wtbl_size)
> > > > > + return;
> > > > > +
> > > > > + rcu_read_lock();
> > > > > +
> > > > > + wcid = rcu_dereference(dev->wcid[wcidx]);
> > > > > + if (!wcid)
> > > > > + goto out;
> > > > > +
> > > > > + mt76_connac3_mac_add_txs_skb(dev, wcid, pid, txs_data);
> > > > > + if (!wcid->sta)
> > > > > + goto out;
> > > > > +
> > > > > + spin_lock_bh(&dev->sta_poll_lock);
> > > > > + if (list_empty(&wcid->poll_list))
> > > > > + list_add_tail(&wcid->poll_list, &dev-
> > > > > >sta_poll_list);
> > > > > + spin_unlock_bh(&dev->sta_poll_lock);
> > > > > +
> > > > > +out:
> > > > > + rcu_read_unlock();
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_add_txs);
> > > > > +
> > > > > +void mt76_connac3_tx_token_put(struct mt76_dev *dev)
> > > > > +{
> > > > > + struct mt76_txwi_cache *txwi;
> > > > > + int id;
> > > > > +
> > > > > + spin_lock_bh(&dev->token_lock);
> > > > > + idr_for_each_entry(&dev->token, txwi, id) {
> > > > > + mt76_connac3_txwi_free(dev, txwi, NULL, NULL);
> > > > > + dev->token_count--;
> > > > > + }
> > > > > + spin_unlock_bh(&dev->token_lock);
> > > > > + idr_destroy(&dev->token);
> > > > > +}
> > > > > +EXPORT_SYMBOL_GPL(mt76_connac3_tx_token_put);
> > > > > diff --git
> > > > > a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > > > b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > > > index 6663a0b46541..bcc1d976b2b0 100644
> > > > > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > > > @@ -4,6 +4,24 @@
> > > > > #ifndef __MT76_CONNAC3_MAC_H
> > > > > #define __MT76_CONNAC3_MAC_H
> > > > >
> > > > > +/* NOTE: used to map mt76_rates. idx may change if firmware
> > > > > expands
> > > > > table */
> > > > > +#define MT76_CONNAC3_BASIC_RATES_TBL 11
> > > > > +#define MT76_CONNAC3_BEACON_RATES_TBL 25
> > > > >
> > > >
> > > > Different devices may have different defined value.
> > >
> > > The other WiFi7 device I am working on relies on the values I
> > > moved
> > > in
> > > mt76_connac3_mac.h (in common with mt7996). Moreover you can
> > > still
> > > have per-device values in mt7996/mac.h (I have not removed it).
> > >
> >
> > Please double check with the mtk folk you work with. The 11 and 25
> > is
> > the value I discussed with firmware folks to avoid overlapping the
> > tbl
> > mt7996 use (MU/other algo in fw), or it causes something hardly
> > solving
> > issue
>
> sure, thx for pointing this out.
> @Deren: can you please double check?
>
> Regards,
> Lorenzo
>
The idx is defined by different flow in fw and may be changed in next
stage development. I think it's better to keep them in per-chip header.
Regards,
Deren
> >
> > > >
> > > > I'm thinking if it's too early to create this patch for just
> > > > moving
> > > > mt7996 to connac3_lib?
> > >
> > > The code I moved is used by the other device as well. This series
> > > is
> > > a
> > > preliminary series to support it.
> > >
> > > Regards,
> > > Lorenzo
> > >
> > > >
> > > > Ryder
> > > >
^ permalink raw reply [flat|nested] 27+ messages in thread* Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library
2023-06-10 2:22 ` Deren Wu (武德仁)
@ 2023-06-10 7:49 ` lorenzo
2023-06-12 8:58 ` Kalle Valo
0 siblings, 1 reply; 27+ messages in thread
From: lorenzo @ 2023-06-10 7:49 UTC (permalink / raw)
To: Deren Wu (武德仁)
Cc: Shayne Chen (陳軒丞), Ryder Lee,
lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org,
nbd@nbd.name
[-- Attachment #1: Type: text/plain, Size: 39219 bytes --]
On Jun 10, Deren Wu wrote:
> On Fri, 2023-06-09 at 18:45 +0200, lorenzo@kernel.org wrote:
> > > On Fri, 2023-06-09 at 18:34 +0200, lorenzo.bianconi@redhat.com
> > > wrote:
> > > > On Jun 09, Ryder Lee wrote:
> > > > > On Fri, 2023-06-09 at 10:15 +0200, Lorenzo Bianconi wrote:
> > > > > >
> > > > > > External email : Please do not click links or open
> > > > > > attachments
> > > > > > until
> > > > > > you have verified the sender or the content.
> > > > > > Introduce connac3_mac in mt76_connac library to reuse mac
> > > > > > code
> > > > > > shared
> > > > > > between WiFi7 chipsets.
> > > > > >
> > > > > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > > > ---
> > > > > > drivers/net/wireless/mediatek/mt76/Makefile | 2 +-
> > > > > > .../net/wireless/mediatek/mt76/mt76_connac.h | 19 +
> > > > > > .../wireless/mediatek/mt76/mt76_connac3_mac.c | 742
> > > > > > +++++++++++++++++
> > > > > > .../wireless/mediatek/mt76/mt76_connac3_mac.h | 18 +
> > > > > > .../net/wireless/mediatek/mt76/mt7996/init.c | 4 +-
> > > > > > .../net/wireless/mediatek/mt76/mt7996/mac.c | 761 +-------
> > > > > > ----
> > > > > > ----
> > > > > > --
> > > > > > .../net/wireless/mediatek/mt76/mt7996/main.c | 8 +-
> > > > > > .../net/wireless/mediatek/mt76/mt7996/mcu.c | 9 +-
> > > > > > .../wireless/mediatek/mt76/mt7996/mt7996.h | 28 +-
> > > > > > 9 files changed, 807 insertions(+), 784 deletions(-)
> > > > > > create mode 100644
> > > > > > drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > > > >
> > > > > > diff --git a/drivers/net/wireless/mediatek/mt76/Makefile
> > > > > > b/drivers/net/wireless/mediatek/mt76/Makefile
> > > > > > index 84c99b7e57f9..d8e8079c8b54 100644
> > > > > > --- a/drivers/net/wireless/mediatek/mt76/Makefile
> > > > > > +++ b/drivers/net/wireless/mediatek/mt76/Makefile
> > > > > > @@ -27,7 +27,7 @@ mt76x02-lib-y := mt76x02_util.o
> > > > > > mt76x02_mac.o
> > > > > > mt76x02_mcu.o \
> > > > > >
> > > > > > mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
> > > > > >
> > > > > > -mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
> > > > > > +mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
> > > > > > mt76_connac3_mac.o
> > > > > >
> > > > > > obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
> > > > > > obj-$(CONFIG_MT76x2_COMMON) += mt76x2/
> > > > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > > > > b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > > > > index 68bdeada1421..20111678537b 100644
> > > > > > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > > > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> > > > > > @@ -415,4 +415,23 @@ void mt76_connac2_txwi_free(struct
> > > > > > mt76_dev
> > > > > > *dev, struct mt76_txwi_cache *t,
> > > > > > struct list_head *free_list);
> > > > > > void mt76_connac2_tx_token_put(struct mt76_dev *dev);
> > > > > >
> > > > > > +/* connac3 */
> > > > > > +void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta,
> > > > > > __le32
> > > > > > *txwi);
> > > > > > +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff
> > > > > > *skb,
> > > > > > __le32
> > > > > > *rxv,
> > > > > > + u8 mode);
> > > > > > +int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev,
> > > > > > + struct mt76_rx_status
> > > > > > *status,
> > > > > > + struct
> > > > > > ieee80211_supported_band
> > > > > > *sband,
> > > > > > + __le32 *rxv, u8 *mode);
> > > > > > +void mt76_connac3_mac_write_txwi(struct mt76_dev *dev,
> > > > > > __le32
> > > > > > *txwi,
> > > > > > + struct sk_buff *skb, struct
> > > > > > mt76_wcid
> > > > > > *wcid,
> > > > > > + struct ieee80211_key_conf
> > > > > > *key, int
> > > > > > pid,
> > > > > > + enum mt76_txq_id qid, u32
> > > > > > changed);
> > > > > > +void mt76_connac3_txwi_free(struct mt76_dev *dev, struct
> > > > > > mt76_txwi_cache *t,
> > > > > > + struct ieee80211_sta *sta,
> > > > > > + struct list_head *free_list);
> > > > > > +void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void
> > > > > > *data,
> > > > > > + u32 max_wtbl_size);
> > > > > > +void mt76_connac3_tx_token_put(struct mt76_dev *dev);
> > > > > > +
> > > > > > #endif /* __MT76_CONNAC_H */
> > > > > > diff --git
> > > > > > a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > > > > b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > > > > new file mode 100644
> > > > > > index 000000000000..4b745bb74ca0
> > > > > > --- /dev/null
> > > > > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
> > > > > > @@ -0,0 +1,742 @@
> > > > > > +// SPDX-License-Identifier: ISC
> > > > > > +/* Copyright (C) 2023 MediaTek Inc. */
> > > > > > +
> > > > > > +#include "mt76_connac.h"
> > > > > > +#include "mt76_connac3_mac.h"
> > > > > > +#include "dma.h"
> > > > > > +
> > > > > > +#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_
> > > > > > HE_##f)
> > > > > > +#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(
> > > > > > v,
> > > > > > MT_CRXV_HE_##m),\
> > > > > > + IEEE80211_RADI
> > > > > > OTAP_HE_
> > > > > > ##f)
> > > > > > +
> > > > > > +void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta,
> > > > > > __le32
> > > > > > *txwi)
> > > > > > +{
> > > > > > + struct mt76_wcid *wcid;
> > > > > > + u16 fc, tid;
> > > > > > + u32 val;
> > > > > > +
> > > > > > + if (!sta ||
> > > > > > + !(sta->deflink.ht_cap.ht_supported || sta-
> > > > > > > deflink.he_cap.has_he))
> > > > > >
> > > > > > + return;
> > > > > > +
> > > > > > + tid = le32_get_bits(txwi[1], MT_TXD1_TID);
> > > > > > + if (tid >= 6) /* skip VO queue */
> > > > > > + return;
> > > > > > +
> > > > > > + val = le32_to_cpu(txwi[2]);
> > > > > > + fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 |
> > > > > > + FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4;
> > > > > > + if (unlikely(fc != (IEEE80211_FTYPE_DATA |
> > > > > > IEEE80211_STYPE_QOS_DATA)))
> > > > > > + return;
> > > > > > +
> > > > > > + wcid = (struct mt76_wcid *)sta->drv_priv;
> > > > > > + if (!test_and_set_bit(tid, &wcid->ampdu_state))
> > > > > > + ieee80211_start_tx_ba_session(sta, tid, 0);
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(mt76_connac3_tx_check_aggr);
> > > > > > +
> > > > > > +static void
> > > > > > +mt76_connac3_mac_decode_he_radiotap_ru(struct mt76_rx_status
> > > > > > *status,
> > > > > > + struct
> > > > > > ieee80211_radiotap_he
> > > > > > *he,
> > > > > > + __le32 *rxv)
> > > > > > +{
> > > > > > + u32 ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC),
> > > > > > offs = 0;
> > > > > > +
> > > > > > + status->bw = RATE_INFO_BW_HE_RU;
> > > > > > +
> > > > > > + switch (ru) {
> > > > > > + case 0 ... 36:
> > > > > > + status->he_ru =
> > > > > > NL80211_RATE_INFO_HE_RU_ALLOC_26;
> > > > > > + offs = ru;
> > > > > > + break;
> > > > > > + case 37 ... 52:
> > > > > > + status->he_ru =
> > > > > > NL80211_RATE_INFO_HE_RU_ALLOC_52;
> > > > > > + offs = ru - 37;
> > > > > > + break;
> > > > > > + case 53 ... 60:
> > > > > > + status->he_ru =
> > > > > > NL80211_RATE_INFO_HE_RU_ALLOC_106;
> > > > > > + offs = ru - 53;
> > > > > > + break;
> > > > > > + case 61 ... 64:
> > > > > > + status->he_ru =
> > > > > > NL80211_RATE_INFO_HE_RU_ALLOC_242;
> > > > > > + offs = ru - 61;
> > > > > > + break;
> > > > > > + case 65 ... 66:
> > > > > > + status->he_ru =
> > > > > > NL80211_RATE_INFO_HE_RU_ALLOC_484;
> > > > > > + offs = ru - 65;
> > > > > > + break;
> > > > > > + case 67:
> > > > > > + status->he_ru =
> > > > > > NL80211_RATE_INFO_HE_RU_ALLOC_996;
> > > > > > + break;
> > > > > > + case 68:
> > > > > > + status->he_ru =
> > > > > > NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
> > > > > > + break;
> > > > > > + }
> > > > > > +
> > > > > > + he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > > > > > + he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
> > > > > > + le16_encode_bits(offs,
> > > > > > + IEEE80211_RADIOTAP_HE_DAT
> > > > > > A2_RU_OF
> > > > > > FSET);
> > > > > > +}
> > > > > > +
> > > > > > +#define MU_PREP(f, v) le16_encode_bits(v,
> > > > > > IEEE80211_RADIOTAP_HE_MU_##f)
> > > > > > +static void
> > > > > > +mt76_connac3_mac_decode_he_mu_radiotap(struct sk_buff *skb,
> > > > > > __le32
> > > > > > *rxv)
> > > > > > +{
> > > > > > + struct mt76_rx_status *status = (struct mt76_rx_status
> > > > > > *)skb-
> > > > > > > cb;
> > > > > >
> > > > > > + static const struct ieee80211_radiotap_he_mu mu_known =
> > > > > > {
> > > > > > + .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
> > > > > > + HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
> > > > > > + HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
> > > > > > + HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KN
> > > > > > OWN),
> > > > > > + .flags2 =
> > > > > > HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
> > > > > > + };
> > > > > > + struct ieee80211_radiotap_he_mu *he_mu;
> > > > > > +
> > > > > > + status->flag |= RX_FLAG_RADIOTAP_HE_MU;
> > > > > > +
> > > > > > + he_mu = skb_push(skb, sizeof(mu_known));
> > > > > > + memcpy(he_mu, &mu_known, sizeof(mu_known));
> > > > > > +
> > > > > > + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status-
> > > > > > >rate_idx);
> > > > > > + if (status->he_dcm)
> > > > > > + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM,
> > > > > > status-
> > > > > > > he_dcm);
> > > > > >
> > > > > > +
> > > > > > + he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW,
> > > > > > status->bw) |
> > > > > > + MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
> > > > > > + le32_get_bits(rxv[4],
> > > > > > MT_CRXV_HE_NUM_USER));
> > > > > > +
> > > > > > + he_mu->ru_ch1[0] = le32_get_bits(rxv[16],
> > > > > > MT_CRXV_HE_RU0) &
> > > > > > 0xff;
> > > > > > +
> > > > > > + if (status->bw >= RATE_INFO_BW_40) {
> > > > > > + he_mu->flags1 |=
> > > > > > HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
> > > > > > + he_mu->ru_ch2[0] = le32_get_bits(rxv[16],
> > > > > > MT_CRXV_HE_RU1) & 0xff;
> > > > > > + }
> > > > > > +
> > > > > > + if (status->bw >= RATE_INFO_BW_80) {
> > > > > > + u32 ru_h, ru_l;
> > > > > > +
> > > > > > + he_mu->ru_ch1[1] = le32_get_bits(rxv[16],
> > > > > > MT_CRXV_HE_RU2) & 0xff;
> > > > > > +
> > > > > > + ru_l = le32_get_bits(rxv[16],
> > > > > > MT_CRXV_HE_RU3_L);
> > > > > > + ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H)
> > > > > > & 0x7;
> > > > > > + he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4);
> > > > > > + }
> > > > > > +}
> > > > > > +
> > > > > > +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff
> > > > > > *skb,
> > > > > > __le32
> > > > > > *rxv,
> > > > > > + u8 mode)
> > > > > > +{
> > > > > > + struct mt76_rx_status *status = (struct mt76_rx_status
> > > > > > *)skb-
> > > > > > > cb;
> > > > > >
> > > > > > + static const struct ieee80211_radiotap_he known = {
> > > > > > + .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
> > > > > > + HE_BITS(DATA1_DATA_DCM_KNOWN) |
> > > > > > + HE_BITS(DATA1_STBC_KNOWN) |
> > > > > > + HE_BITS(DATA1_CODING_KNOWN) |
> > > > > > + HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
> > > > > > + HE_BITS(DATA1_DOPPLER_KNOWN) |
> > > > > > + HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
> > > > > > + HE_BITS(DATA1_BSS_COLOR_KNOWN),
> > > > > > + .data2 = HE_BITS(DATA2_GI_KNOWN) |
> > > > > > + HE_BITS(DATA2_TXBF_KNOWN) |
> > > > > > + HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
> > > > > > + HE_BITS(DATA2_TXOP_KNOWN),
> > > > > > + };
> > > > > > + u32 ltf_size = le32_get_bits(rxv[4],
> > > > > > MT_CRXV_HE_LTF_SIZE) + 1;
> > > > > > + struct ieee80211_radiotap_he *he;
> > > > > > +
> > > > > > + status->flag |= RX_FLAG_RADIOTAP_HE;
> > > > > > +
> > > > > > + he = skb_push(skb, sizeof(known));
> > > > > > + memcpy(he, &known, sizeof(known));
> > > > > > +
> > > > > > + he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9])
> > > > > > |
> > > > > > + HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM,
> > > > > > rxv[4]);
> > > > > > + he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK,
> > > > > > rxv[13]);
> > > > > > + he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG,
> > > > > > rxv[5]) |
> > > > > > + le16_encode_bits(ltf_size,
> > > > > > + IEEE80211_RADIOTAP_HE_DATA
> > > > > > 5_LTF_SI
> > > > > > ZE);
> > > > > > + if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
> > > > > > + he->data5 |= HE_BITS(DATA5_TXBF);
> > > > > > + he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) |
> > > > > > + HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]);
> > > > > > +
> > > > > > + switch (mode) {
> > > > > > + case MT_PHY_TYPE_HE_SU:
> > > > > > + he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
> > > > > > + HE_BITS(DATA1_UL_DL_KNOWN) |
> > > > > > + HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
> > > > > > + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > > > > > +
> > > > > > + he->data3 |= HE_PREP(DATA3_BEAM_CHANGE,
> > > > > > BEAM_CHNG,
> > > > > > rxv[8]) |
> > > > > > + HE_PREP(DATA3_UL_DL, UPLINK,
> > > > > > rxv[5]);
> > > > > > + break;
> > > > > > + case MT_PHY_TYPE_HE_EXT_SU:
> > > > > > + he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
> > > > > > + HE_BITS(DATA1_UL_DL_KNOWN) |
> > > > > > + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
> > > > > > +
> > > > > > + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK,
> > > > > > rxv[5]);
> > > > > > + break;
> > > > > > + case MT_PHY_TYPE_HE_MU:
> > > > > > + he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
> > > > > > + HE_BITS(DATA1_UL_DL_KNOWN);
> > > > > > +
> > > > > > + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK,
> > > > > > rxv[5]);
> > > > > > + he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID,
> > > > > > rxv[8]);
> > > > > > +
> > > > > > + mt76_connac3_mac_decode_he_radiotap_ru(status,
> > > > > > he,
> > > > > > rxv);
> > > > > > + mt76_connac3_mac_decode_he_mu_radiotap(skb,
> > > > > > rxv);
> > > > > > + break;
> > > > > > + case MT_PHY_TYPE_HE_TB:
> > > > > > + he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
> > > > > > + HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
> > > > > > + HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
> > > > > > + HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
> > > > > > +
> > > > > > + he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1,
> > > > > > SR_MASK,
> > > > > > rxv[13]) |
> > > > > > + HE_PREP(DATA4_TB_SPTL_REUSE2,
> > > > > > SR1_MASK,
> > > > > > rxv[13]) |
> > > > > > + HE_PREP(DATA4_TB_SPTL_REUSE3,
> > > > > > SR2_MASK,
> > > > > > rxv[13]) |
> > > > > > + HE_PREP(DATA4_TB_SPTL_REUSE4,
> > > > > > SR3_MASK,
> > > > > > rxv[13]);
> > > > > > +
> > > > > > + mt76_connac3_mac_decode_he_radiotap_ru(status,
> > > > > > he,
> > > > > > rxv);
> > > > > > + break;
> > > > > > + default:
> > > > > > + break;
> > > > > > + }
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap);
> > > > > > +
> > > > > > +int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev,
> > > > > > + struct mt76_rx_status
> > > > > > *status,
> > > > > > + struct
> > > > > > ieee80211_supported_band
> > > > > > *sband,
> > > > > > + __le32 *rxv, u8 *mode)
> > > > > > +{
> > > > > > + u8 stbc, gi, bw, dcm, nss;
> > > > > > + bool cck = false;
> > > > > > + u32 v0, v2;
> > > > > > + int i, idx;
> > > > > > +
> > > > > > + v0 = le32_to_cpu(rxv[0]);
> > > > > > + v2 = le32_to_cpu(rxv[2]);
> > > > > > +
> > > > > > + idx = FIELD_GET(MT_PRXV_TX_RATE, v0);
> > > > > > + i = idx;
> > > > > > + nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1;
> > > > > > +
> > > > > > + stbc = FIELD_GET(MT_PRXV_HT_STBC, v2);
> > > > > > + gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2);
> > > > > > + *mode = FIELD_GET(MT_PRXV_TX_MODE, v2);
> > > > > > + dcm = FIELD_GET(MT_PRXV_DCM, v2);
> > > > > > + bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2);
> > > > > > +
> > > > > > + switch (*mode) {
> > > > > > + case MT_PHY_TYPE_CCK:
> > > > > > + cck = true;
> > > > > > + fallthrough;
> > > > > > + case MT_PHY_TYPE_OFDM:
> > > > > > + i = mt76_get_rate(dev, sband, i, cck);
> > > > > > + break;
> > > > > > + case MT_PHY_TYPE_HT_GF:
> > > > > > + case MT_PHY_TYPE_HT:
> > > > > > + status->encoding = RX_ENC_HT;
> > > > > > + if (gi)
> > > > > > + status->enc_flags |=
> > > > > > RX_ENC_FLAG_SHORT_GI;
> > > > > > + if (i > 31)
> > > > > > + return -EINVAL;
> > > > > > + break;
> > > > > > + case MT_PHY_TYPE_VHT:
> > > > > > + status->nss = nss;
> > > > > > + status->encoding = RX_ENC_VHT;
> > > > > > + if (gi)
> > > > > > + status->enc_flags |=
> > > > > > RX_ENC_FLAG_SHORT_GI;
> > > > > > + if (i > 11)
> > > > > > + return -EINVAL;
> > > > > > + break;
> > > > > > + case MT_PHY_TYPE_HE_MU:
> > > > > > + case MT_PHY_TYPE_HE_SU:
> > > > > > + case MT_PHY_TYPE_HE_EXT_SU:
> > > > > > + case MT_PHY_TYPE_HE_TB:
> > > > > > + status->nss = nss;
> > > > > > + status->encoding = RX_ENC_HE;
> > > > > > + i &= GENMASK(3, 0);
> > > > > > +
> > > > > > + if (gi <= NL80211_RATE_INFO_HE_GI_3_2)
> > > > > > + status->he_gi = gi;
> > > > > > +
> > > > > > + status->he_dcm = dcm;
> > > > > > + break;
> > > > > > + case MT_PHY_TYPE_EHT_SU:
> > > > > > + case MT_PHY_TYPE_EHT_TRIG:
> > > > > > + case MT_PHY_TYPE_EHT_MU:
> > > > > > + status->nss = nss;
> > > > > > + status->encoding = RX_ENC_EHT;
> > > > > > + i &= GENMASK(3, 0);
> > > > > > +
> > > > > > + if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
> > > > > > + status->eht.gi = gi;
> > > > > > + break;
> > > > > > + default:
> > > > > > + return -EINVAL;
> > > > > > + }
> > > > > > + status->rate_idx = i;
> > > > > > +
> > > > > > + switch (bw) {
> > > > > > + case IEEE80211_STA_RX_BW_20:
> > > > > > + break;
> > > > > > + case IEEE80211_STA_RX_BW_40:
> > > > > > + if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
> > > > > > + (idx & MT_PRXV_TX_ER_SU_106T)) {
> > > > > > + status->bw = RATE_INFO_BW_HE_RU;
> > > > > > + status->he_ru =
> > > > > > + NL80211_RATE_INFO_HE_RU_ALLOC_1
> > > > > > 06;
> > > > > > + } else {
> > > > > > + status->bw = RATE_INFO_BW_40;
> > > > > > + }
> > > > > > + break;
> > > > > > + case IEEE80211_STA_RX_BW_80:
> > > > > > + status->bw = RATE_INFO_BW_80;
> > > > > > + break;
> > > > > > + case IEEE80211_STA_RX_BW_160:
> > > > > > + status->bw = RATE_INFO_BW_160;
> > > > > > + break;
> > > > > > + case IEEE80211_STA_RX_BW_320:
> > > > > > + status->bw = RATE_INFO_BW_320;
> > > > > > + break;
> > > > > > + default:
> > > > > > + return -EINVAL;
> > > > > > + }
> > > > > > +
> > > > > > + status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
> > > > > > + if (*mode < MT_PHY_TYPE_HE_SU && gi)
> > > > > > + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
> > > > > > +
> > > > > > + return 0;
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_fill_rx_rate);
> > > > > > +
> > > > > > +static void
> > > > > > +mt76_connac3_mac_write_txwi_8023(__le32 *txwi, struct
> > > > > > sk_buff
> > > > > > *skb,
> > > > > > + struct mt76_wcid *wcid)
> > > > > > +{
> > > > > > + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
> > > > > > + u8 fc_type, fc_stype;
> > > > > > + u16 ethertype;
> > > > > > + bool wmm = false;
> > > > > > + u32 val;
> > > > > > +
> > > > > > + if (wcid->sta) {
> > > > > > + struct ieee80211_sta *sta;
> > > > > > +
> > > > > > + sta = container_of((void *)wcid, struct
> > > > > > ieee80211_sta,
> > > > > > drv_priv);
> > > > > > + wmm = sta->wme;
> > > > > > + }
> > > > > > +
> > > > > > + val = FIELD_PREP(MT_TXD1_HDR_FORMAT,
> > > > > > MT_HDR_FORMAT_802_3) |
> > > > > > + FIELD_PREP(MT_TXD1_TID, tid);
> > > > > > +
> > > > > > + ethertype = get_unaligned_be16(&skb->data[12]);
> > > > > > + if (ethertype >= ETH_P_802_3_MIN)
> > > > > > + val |= MT_TXD1_ETH_802_3;
> > > > > > +
> > > > > > + txwi[1] |= cpu_to_le32(val);
> > > > > > +
> > > > > > + fc_type = IEEE80211_FTYPE_DATA >> 2;
> > > > > > + fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0;
> > > > > > +
> > > > > > + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
> > > > > > + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
> > > > > > +
> > > > > > + txwi[2] |= cpu_to_le32(val);
> > > > > > +}
> > > > > > +
> > > > > > +static void
> > > > > > +mt76_connac3_mac_write_txwi_80211(struct mt76_dev *dev,
> > > > > > __le32
> > > > > > *txwi,
> > > > > > + struct sk_buff *skb,
> > > > > > + struct ieee80211_key_conf
> > > > > > *key)
> > > > > > +{
> > > > > > + struct ieee80211_hdr *hdr = (struct ieee80211_hdr
> > > > > > *)skb->data;
> > > > > > + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt
> > > > > > *)skb-
> > > > > > > data;
> > > > > >
> > > > > > + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> > > > > > + bool multicast = is_multicast_ether_addr(hdr->addr1);
> > > > > > + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
> > > > > > + __le16 fc = hdr->frame_control;
> > > > > > + u8 fc_type, fc_stype;
> > > > > > + u32 val;
> > > > > > +
> > > > > > + if (ieee80211_is_action(fc) &&
> > > > > > + mgmt->u.action.category == WLAN_CATEGORY_BACK &&
> > > > > > + mgmt->u.action.u.addba_req.action_code ==
> > > > > > WLAN_ACTION_ADDBA_REQ)
> > > > > > + tid = MT_TX_ADDBA;
> > > > > > + else if (ieee80211_is_mgmt(hdr->frame_control))
> > > > > > + tid = MT_TX_NORMAL;
> > > > > > +
> > > > > > + val = FIELD_PREP(MT_TXD1_HDR_FORMAT,
> > > > > > MT_HDR_FORMAT_802_11) |
> > > > > > + FIELD_PREP(MT_TXD1_HDR_INFO,
> > > > > > + ieee80211_get_hdrlen_from_skb(skb) /
> > > > > > 2) |
> > > > > > + FIELD_PREP(MT_TXD1_TID, tid);
> > > > > > +
> > > > > > + if (!ieee80211_is_data(fc) || multicast ||
> > > > > > + info->flags & IEEE80211_TX_CTL_USE_MINRATE)
> > > > > > + val |= MT_TXD1_FIXED_RATE;
> > > > > > +
> > > > > > + if (key && multicast &&
> > > > > > ieee80211_is_robust_mgmt_frame(skb) &&
> > > > > > + key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
> > > > > > + val |= MT_TXD1_BIP;
> > > > > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
> > > > > > + }
> > > > > > +
> > > > > > + txwi[1] |= cpu_to_le32(val);
> > > > > > +
> > > > > > + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >>
> > > > > > 2;
> > > > > > + fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >>
> > > > > > 4;
> > > > > > +
> > > > > > + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
> > > > > > + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
> > > > > > +
> > > > > > + txwi[2] |= cpu_to_le32(val);
> > > > > > +
> > > > > > + txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM,
> > > > > > multicast));
> > > > > > + if (ieee80211_is_beacon(fc)) {
> > > > > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT);
> > > > > > + txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
> > > > > > + }
> > > > > > +
> > > > > > + if (info->flags & IEEE80211_TX_CTL_INJECTED) {
> > > > > > + u16 seqno = le16_to_cpu(hdr->seq_ctrl);
> > > > > > +
> > > > > > + if (ieee80211_is_back_req(hdr->frame_control))
> > > > > > {
> > > > > > + struct ieee80211_bar *bar;
> > > > > > +
> > > > > > + bar = (struct ieee80211_bar *)skb-
> > > > > > >data;
> > > > > > + seqno = le16_to_cpu(bar-
> > > > > > >start_seq_num);
> > > > > > + }
> > > > > > +
> > > > > > + val = MT_TXD3_SN_VALID |
> > > > > > + FIELD_PREP(MT_TXD3_SEQ,
> > > > > > IEEE80211_SEQ_TO_SN(seqno));
> > > > > > + txwi[3] |= cpu_to_le32(val);
> > > > > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
> > > > > > + }
> > > > > > +}
> > > > > > +
> > > > > > +void mt76_connac3_mac_write_txwi(struct mt76_dev *dev,
> > > > > > __le32
> > > > > > *txwi,
> > > > > > + struct sk_buff *skb, struct
> > > > > > mt76_wcid
> > > > > > *wcid,
> > > > > > + struct ieee80211_key_conf
> > > > > > *key, int
> > > > > > pid,
> > > > > > + enum mt76_txq_id qid, u32
> > > > > > changed)
> > > > > > +{
> > > > > > + u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE :
> > > > > > MT_SDIO_TXD_SIZE;
> > > > > > + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> > > > > > + struct ieee80211_vif *vif = info->control.vif;
> > > > > > + u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >>
> > > > > > 2;
> > > > > > + u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
> > > > > > + bool is_8023 = info->flags &
> > > > > > IEEE80211_TX_CTL_HW_80211_ENCAP;
> > > > > > + struct mt76_vif *mvif;
> > > > > > + u16 tx_count = 15;
> > > > > > + bool beacon = !!(changed & (BSS_CHANGED_BEACON |
> > > > > > + BSS_CHANGED_BEACON_ENABLED)
> > > > > > );
> > > > > > + bool inband_disc = !!(changed &
> > > > > > (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
> > > > > > + BSS_CHANGED_FILS_DISCO
> > > > > > VERY));
> > > > > > +
> > > > > > + mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL;
> > > > > > + if (mvif) {
> > > > > > + omac_idx = mvif->omac_idx;
> > > > > > + wmm_idx = mvif->wmm_idx;
> > > > > > + band_idx = mvif->band_idx;
> > > > > > + }
> > > > > > +
> > > > > > + if (inband_disc) {
> > > > > > + p_fmt = MT_TX_TYPE_FW;
> > > > > > + q_idx = MT_LMAC_ALTX0;
> > > > > > + } else if (beacon) {
> > > > > > + p_fmt = MT_TX_TYPE_FW;
> > > > > > + q_idx = MT_LMAC_BCN0;
> > > > > > + } else if (qid >= MT_TXQ_PSD) {
> > > > > > + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT :
> > > > > > MT_TX_TYPE_SF;
> > > > > > + q_idx = MT_LMAC_ALTX0;
> > > > > > + } else {
> > > > > > + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT :
> > > > > > MT_TX_TYPE_SF;
> > > > > > + q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS +
> > > > > > + mt76_connac_lmac_mapping(skb_get_queue_
> > > > > > mapping(
> > > > > > skb));
> > > > > > + }
> > > > > > +
> > > > > > + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
> > > > > > + FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
> > > > > > + FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
> > > > > > + txwi[0] = cpu_to_le32(val);
> > > > > > +
> > > > > > + val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
> > > > > > + FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
> > > > > > +
> > > > > > + if (band_idx)
> > > > > > + val |= FIELD_PREP(MT_TXD1_TGID, band_idx);
> > > > > > +
> > > > > > + txwi[1] = cpu_to_le32(val);
> > > > > > + txwi[2] = 0;
> > > > > > +
> > > > > > + val = MT_TXD3_SW_POWER_MGMT |
> > > > > > + FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count);
> > > > > > + if (key)
> > > > > > + val |= MT_TXD3_PROTECT_FRAME;
> > > > > > + if (info->flags & IEEE80211_TX_CTL_NO_ACK)
> > > > > > + val |= MT_TXD3_NO_ACK;
> > > > > > + if (wcid->amsdu)
> > > > > > + val |= MT_TXD3_HW_AMSDU;
> > > > > > +
> > > > > > + txwi[3] = cpu_to_le32(val);
> > > > > > + txwi[4] = 0;
> > > > > > +
> > > > > > + val = FIELD_PREP(MT_TXD5_PID, pid);
> > > > > > + if (pid >= MT_PACKET_ID_FIRST)
> > > > > > + val |= MT_TXD5_TX_STATUS_HOST;
> > > > > > + txwi[5] = cpu_to_le32(val);
> > > > > > +
> > > > > > + val = MT_TXD6_DIS_MAT | MT_TXD6_DAS |
> > > > > > + FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
> > > > > > + txwi[6] = cpu_to_le32(val);
> > > > > > + txwi[7] = 0;
> > > > > > +
> > > > > > + if (is_8023)
> > > > > > + mt76_connac3_mac_write_txwi_8023(txwi, skb,
> > > > > > wcid);
> > > > > > + else
> > > > > > + mt76_connac3_mac_write_txwi_80211(dev, txwi,
> > > > > > skb, key);
> > > > > > +
> > > > > > + if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
> > > > > > + struct ieee80211_hdr *hdr = (struct
> > > > > > ieee80211_hdr
> > > > > > *)skb->data;
> > > > > > + bool mcast = ieee80211_is_data(hdr-
> > > > > > >frame_control) &&
> > > > > > + is_multicast_ether_addr(hdr-
> > > > > > >addr1);
> > > > > > + u8 idx = MT76_CONNAC3_BASIC_RATES_TBL;
> > > > > > +
> > > > > > + if (mvif) {
> > > > > > + if (mcast && mvif->mcast_rates_idx)
> > > > > > + idx = mvif->mcast_rates_idx;
> > > > > > + else if (beacon && mvif-
> > > > > > >beacon_rates_idx)
> > > > > > + idx = mvif->beacon_rates_idx;
> > > > > > + else
> > > > > > + idx = mvif->basic_rates_idx;
> > > > > > + }
> > > > > > +
> > > > > > + txwi[6] |=
> > > > > > cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE,
> > > > > > idx));
> > > > > > + txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
> > > > > > + }
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_write_txwi);
> > > > > > +
> > > > > > +void mt76_connac3_txwi_free(struct mt76_dev *dev, struct
> > > > > > mt76_txwi_cache *t,
> > > > > > + struct ieee80211_sta *sta,
> > > > > > + struct list_head *free_list)
> > > > > > +{
> > > > > > + __le32 *txwi;
> > > > > > + u16 wcid_idx;
> > > > > > +
> > > > > > + mt76_connac_txp_skb_unmap(dev, t);
> > > > > > + if (!t->skb)
> > > > > > + goto out;
> > > > > > +
> > > > > > + txwi = (__le32 *)mt76_get_txwi_ptr(dev, t);
> > > > > > + if (sta) {
> > > > > > + struct mt76_wcid *wcid = (struct mt76_wcid
> > > > > > *)sta-
> > > > > > > drv_priv;
> > > > > >
> > > > > > +
> > > > > > + wcid_idx = wcid->idx;
> > > > > > + if (likely(t->skb->protocol !=
> > > > > > cpu_to_be16(ETH_P_PAE)))
> > > > > > + mt76_connac3_tx_check_aggr(sta, txwi);
> > > > > > + } else {
> > > > > > + wcid_idx = le32_get_bits(txwi[1],
> > > > > > MT_TXD1_WLAN_IDX);
> > > > > > + }
> > > > > > +
> > > > > > + __mt76_tx_complete_skb(dev, wcid_idx, t->skb,
> > > > > > free_list);
> > > > > > +out:
> > > > > > + t->skb = NULL;
> > > > > > + mt76_put_txwi(dev, t);
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(mt76_connac3_txwi_free);
> > > > > > +
> > > > > > +static bool
> > > > > > +mt76_connac3_mac_add_txs_skb(struct mt76_dev *dev, struct
> > > > > > mt76_wcid
> > > > > > *wcid,
> > > > > > + int pid, __le32 *txs_data)
> > > > > > +{
> > > > > > + struct mt76_sta_stats *stats = &wcid->stats;
> > > > > > + struct ieee80211_supported_band *sband;
> > > > > > + struct ieee80211_tx_info *info;
> > > > > > + u32 txrate, txs, mode, stbc;
> > > > > > + struct rate_info rate = {};
> > > > > > + struct sk_buff_head list;
> > > > > > + struct mt76_phy *mphy;
> > > > > > + struct sk_buff *skb;
> > > > > > + bool cck = false;
> > > > > > +
> > > > > > + mt76_tx_status_lock(dev, &list);
> > > > > > + skb = mt76_tx_status_skb_get(dev, wcid, pid, &list);
> > > > > > + if (!skb)
> > > > > > + goto out_no_skb;
> > > > > > +
> > > > > > + txs = le32_to_cpu(txs_data[0]);
> > > > > > +
> > > > > > + info = IEEE80211_SKB_CB(skb);
> > > > > > + if (!(txs & MT_TXS0_ACK_ERROR_MASK))
> > > > > > + info->flags |= IEEE80211_TX_STAT_ACK;
> > > > > > +
> > > > > > + info->status.ampdu_len = 1;
> > > > > > + info->status.ampdu_ack_len = !!(info->flags &
> > > > > > + IEEE80211_TX_STAT_ACK);
> > > > > > + info->status.rates[0].idx = -1;
> > > > > > +
> > > > > > + txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
> > > > > > +
> > > > > > + rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate);
> > > > > > + rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1;
> > > > > > + stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC);
> > > > > > +
> > > > > > + if (stbc && rate.nss > 1)
> > > > > > + rate.nss >>= 1;
> > > > > > +
> > > > > > + if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss))
> > > > > > + stats->tx_nss[rate.nss - 1]++;
> > > > > > + if (rate.mcs < ARRAY_SIZE(stats->tx_mcs))
> > > > > > + stats->tx_mcs[rate.mcs]++;
> > > > > > +
> > > > > > + mode = FIELD_GET(MT_TX_RATE_MODE, txrate);
> > > > > > + switch (mode) {
> > > > > > + case MT_PHY_TYPE_CCK:
> > > > > > + cck = true;
> > > > > > + fallthrough;
> > > > > > + case MT_PHY_TYPE_OFDM:
> > > > > > + mphy = mt76_dev_phy(dev, wcid->phy_idx);
> > > > > > +
> > > > > > + if (mphy->chandef.chan->band ==
> > > > > > NL80211_BAND_5GHZ)
> > > > > > + sband = &mphy->sband_5g.sband;
> > > > > > + else if (mphy->chandef.chan->band ==
> > > > > > NL80211_BAND_6GHZ)
> > > > > > + sband = &mphy->sband_6g.sband;
> > > > > > + else
> > > > > > + sband = &mphy->sband_2g.sband;
> > > > > > +
> > > > > > + rate.mcs = mt76_get_rate(mphy->dev, sband,
> > > > > > rate.mcs,
> > > > > > cck);
> > > > > > + rate.legacy = sband-
> > > > > > >bitrates[rate.mcs].bitrate;
> > > > > > + break;
> > > > > > + case MT_PHY_TYPE_HT:
> > > > > > + case MT_PHY_TYPE_HT_GF:
> > > > > > + if (rate.mcs > 31)
> > > > > > + goto out;
> > > > > > +
> > > > > > + rate.flags = RATE_INFO_FLAGS_MCS;
> > > > > > + if (wcid->rate.flags &
> > > > > > RATE_INFO_FLAGS_SHORT_GI)
> > > > > > + rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
> > > > > > + break;
> > > > > > + case MT_PHY_TYPE_VHT:
> > > > > > + if (rate.mcs > 9)
> > > > > > + goto out;
> > > > > > +
> > > > > > + rate.flags = RATE_INFO_FLAGS_VHT_MCS;
> > > > > > + break;
> > > > > > + case MT_PHY_TYPE_HE_SU:
> > > > > > + case MT_PHY_TYPE_HE_EXT_SU:
> > > > > > + case MT_PHY_TYPE_HE_TB:
> > > > > > + case MT_PHY_TYPE_HE_MU:
> > > > > > + if (rate.mcs > 11)
> > > > > > + goto out;
> > > > > > +
> > > > > > + rate.he_gi = wcid->rate.he_gi;
> > > > > > + rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM,
> > > > > > txrate);
> > > > > > + rate.flags = RATE_INFO_FLAGS_HE_MCS;
> > > > > > + break;
> > > > > > + case MT_PHY_TYPE_EHT_SU:
> > > > > > + case MT_PHY_TYPE_EHT_TRIG:
> > > > > > + case MT_PHY_TYPE_EHT_MU:
> > > > > > + if (rate.mcs > 13)
> > > > > > + goto out;
> > > > > > +
> > > > > > + rate.eht_gi = wcid->rate.eht_gi;
> > > > > > + rate.flags = RATE_INFO_FLAGS_EHT_MCS;
> > > > > > + break;
> > > > > > + default:
> > > > > > + goto out;
> > > > > > + }
> > > > > > +
> > > > > > + stats->tx_mode[mode]++;
> > > > > > +
> > > > > > + switch (FIELD_GET(MT_TXS0_BW, txs)) {
> > > > > > + case IEEE80211_STA_RX_BW_320:
> > > > > > + rate.bw = RATE_INFO_BW_320;
> > > > > > + stats->tx_bw[4]++;
> > > > > > + break;
> > > > > > + case IEEE80211_STA_RX_BW_160:
> > > > > > + rate.bw = RATE_INFO_BW_160;
> > > > > > + stats->tx_bw[3]++;
> > > > > > + break;
> > > > > > + case IEEE80211_STA_RX_BW_80:
> > > > > > + rate.bw = RATE_INFO_BW_80;
> > > > > > + stats->tx_bw[2]++;
> > > > > > + break;
> > > > > > + case IEEE80211_STA_RX_BW_40:
> > > > > > + rate.bw = RATE_INFO_BW_40;
> > > > > > + stats->tx_bw[1]++;
> > > > > > + break;
> > > > > > + default:
> > > > > > + rate.bw = RATE_INFO_BW_20;
> > > > > > + stats->tx_bw[0]++;
> > > > > > + break;
> > > > > > + }
> > > > > > + wcid->rate = rate;
> > > > > > +
> > > > > > +out:
> > > > > > + mt76_tx_status_skb_done(dev, skb, &list);
> > > > > > +
> > > > > > +out_no_skb:
> > > > > > + mt76_tx_status_unlock(dev, &list);
> > > > > > +
> > > > > > + return !!skb;
> > > > > > +}
> > > > > > +
> > > > > > +void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void
> > > > > > *data,
> > > > > > + u32 max_wtbl_size)
> > > > > > +{
> > > > > > + struct mt76_wcid *wcid;
> > > > > > + __le32 *txs_data = data;
> > > > > > + u16 wcidx;
> > > > > > + u8 pid;
> > > > > > +
> > > > > > + if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
> > > > > > + return;
> > > > > > +
> > > > > > + wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
> > > > > > + pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
> > > > > > +
> > > > > > + if (pid < MT_PACKET_ID_FIRST)
> > > > > > + return;
> > > > > > +
> > > > > > + if (wcidx >= max_wtbl_size)
> > > > > > + return;
> > > > > > +
> > > > > > + rcu_read_lock();
> > > > > > +
> > > > > > + wcid = rcu_dereference(dev->wcid[wcidx]);
> > > > > > + if (!wcid)
> > > > > > + goto out;
> > > > > > +
> > > > > > + mt76_connac3_mac_add_txs_skb(dev, wcid, pid, txs_data);
> > > > > > + if (!wcid->sta)
> > > > > > + goto out;
> > > > > > +
> > > > > > + spin_lock_bh(&dev->sta_poll_lock);
> > > > > > + if (list_empty(&wcid->poll_list))
> > > > > > + list_add_tail(&wcid->poll_list, &dev-
> > > > > > >sta_poll_list);
> > > > > > + spin_unlock_bh(&dev->sta_poll_lock);
> > > > > > +
> > > > > > +out:
> > > > > > + rcu_read_unlock();
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_add_txs);
> > > > > > +
> > > > > > +void mt76_connac3_tx_token_put(struct mt76_dev *dev)
> > > > > > +{
> > > > > > + struct mt76_txwi_cache *txwi;
> > > > > > + int id;
> > > > > > +
> > > > > > + spin_lock_bh(&dev->token_lock);
> > > > > > + idr_for_each_entry(&dev->token, txwi, id) {
> > > > > > + mt76_connac3_txwi_free(dev, txwi, NULL, NULL);
> > > > > > + dev->token_count--;
> > > > > > + }
> > > > > > + spin_unlock_bh(&dev->token_lock);
> > > > > > + idr_destroy(&dev->token);
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_GPL(mt76_connac3_tx_token_put);
> > > > > > diff --git
> > > > > > a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > > > > b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > > > > index 6663a0b46541..bcc1d976b2b0 100644
> > > > > > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > > > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
> > > > > > @@ -4,6 +4,24 @@
> > > > > > #ifndef __MT76_CONNAC3_MAC_H
> > > > > > #define __MT76_CONNAC3_MAC_H
> > > > > >
> > > > > > +/* NOTE: used to map mt76_rates. idx may change if firmware
> > > > > > expands
> > > > > > table */
> > > > > > +#define MT76_CONNAC3_BASIC_RATES_TBL 11
> > > > > > +#define MT76_CONNAC3_BEACON_RATES_TBL 25
> > > > > >
> > > > >
> > > > > Different devices may have different defined value.
> > > >
> > > > The other WiFi7 device I am working on relies on the values I
> > > > moved
> > > > in
> > > > mt76_connac3_mac.h (in common with mt7996). Moreover you can
> > > > still
> > > > have per-device values in mt7996/mac.h (I have not removed it).
> > > >
> > >
> > > Please double check with the mtk folk you work with. The 11 and 25
> > > is
> > > the value I discussed with firmware folks to avoid overlapping the
> > > tbl
> > > mt7996 use (MU/other algo in fw), or it causes something hardly
> > > solving
> > > issue
> >
> > sure, thx for pointing this out.
> > @Deren: can you please double check?
> >
> > Regards,
> > Lorenzo
> >
> The idx is defined by different flow in fw and may be changed in next
> stage development. I think it's better to keep them in per-chip header.
ack, I will fix it.
Regards,
Lorenzo
>
> Regards,
> Deren
>
> > >
> > > > >
> > > > > I'm thinking if it's too early to create this patch for just
> > > > > moving
> > > > > mt7996 to connac3_lib?
> > > >
> > > > The code I moved is used by the other device as well. This series
> > > > is
> > > > a
> > > > preliminary series to support it.
> > > >
> > > > Regards,
> > > > Lorenzo
> > > >
> > > > >
> > > > > Ryder
> > > > >
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread* Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library
2023-06-10 7:49 ` lorenzo
@ 2023-06-12 8:58 ` Kalle Valo
0 siblings, 0 replies; 27+ messages in thread
From: Kalle Valo @ 2023-06-12 8:58 UTC (permalink / raw)
To: lorenzo@kernel.org
Cc: Deren Wu (武德仁),
Shayne Chen (陳軒丞), Ryder Lee,
lorenzo.bianconi@redhat.com, linux-wireless@vger.kernel.org,
nbd@nbd.name
"lorenzo@kernel.org" <lorenzo@kernel.org> writes:
> On Jun 10, Deren Wu wrote:
>> On Fri, 2023-06-09 at 18:45 +0200, lorenzo@kernel.org wrote:
>> > > On Fri, 2023-06-09 at 18:34 +0200, lorenzo.bianconi@redhat.com
>> > > wrote:
>> > > > On Jun 09, Ryder Lee wrote:
>> > > > > On Fri, 2023-06-09 at 10:15 +0200, Lorenzo Bianconi wrote:
>> > > > > >
Guys, please edit your quotes. You are now sending mails with 1000 lines
and that makes it unreadable in patchwork:
https://patchwork.kernel.org/project/linux-wireless/patch/b7a029d6dfee8e58c58f483ea9e9e7b3bc8012b9.1686298162.git.lorenzo@kernel.org/
--
https://patchwork.kernel.org/project/linux-wireless/list/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply [flat|nested] 27+ messages in thread