2023-06-09 08:18:57

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 00/15] mt76: introduce connac3_mac support

Introduce connac3_mac in mt76_connac library to reuse mac code shared
between WiFi7 chipsets.
Move the following common mac fields in mt76_struct/mt76_wcid:
- sta_poll_list
- sta_poll_lock
- poll_list
- ampdu_state

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

Changes since v1:
- rebase on top wireless-next tree
- fix connac3_mac library
- fix compilation warnings

Lorenzo Bianconi (15):
wifi: mt76: mt7915: move sta_poll_list and sta_poll_lock in mt76_dev
wifi: mt76: mt7603: rely on shared sta_poll_list and sta_poll_lock
wifi: mt76: mt7615: rely on shared sta_poll_list and sta_poll_lock
wifi: mt76: mt7996: rely on shared sta_poll_list and sta_poll_lock
wifi: mt76: mt7921: rely on shared sta_poll_list and sta_poll_lock
wifi: mt76: mt7915: move poll_list in mt76_wcid
wifi: mt76: mt7603: rely on shared poll_list field
wifi: mt76: mt7615: rely on shared poll_list field
wifi: mt76: mt7996: rely on shared poll_list field
wifi: mt76: mt7921: rely on shared poll_list field
wifi: mt76: move ampdu_state in mt76_wcid
mt76: connac: move more mt7921/mt7915 mac shared code in connac lib
wifi: mt76: move rate info in mt76_vif
wifi: mt76: connac: move connac3 definitions in mt76_connac3_mac.h
wifi: mt76: connac: add connac3 mac library

drivers/net/wireless/mediatek/mt76/Makefile | 2 +-
drivers/net/wireless/mediatek/mt76/mac80211.c | 2 +
drivers/net/wireless/mediatek/mt76/mt76.h | 9 +
.../net/wireless/mediatek/mt76/mt7603/init.c | 2 -
.../net/wireless/mediatek/mt76/mt7603/mac.c | 22 +-
.../net/wireless/mediatek/mt76/mt7603/main.c | 20 +-
.../wireless/mediatek/mt76/mt7603/mt7603.h | 4 -
.../net/wireless/mediatek/mt76/mt7615/init.c | 2 -
.../net/wireless/mediatek/mt76/mt7615/mac.c | 31 +-
.../net/wireless/mediatek/mt76/mt7615/main.c | 20 +-
.../wireless/mediatek/mt76/mt7615/mt7615.h | 4 -
.../net/wireless/mediatek/mt76/mt76_connac.h | 24 +
.../wireless/mediatek/mt76/mt76_connac3_mac.c | 742 ++++++++++++++++
.../wireless/mediatek/mt76/mt76_connac3_mac.h | 343 ++++++++
.../wireless/mediatek/mt76/mt76_connac_mac.c | 82 ++
.../net/wireless/mediatek/mt76/mt7915/init.c | 4 +-
.../net/wireless/mediatek/mt76/mt7915/mac.c | 140 +--
.../net/wireless/mediatek/mt76/mt7915/main.c | 30 +-
.../wireless/mediatek/mt76/mt7915/mt7915.h | 5 -
.../net/wireless/mediatek/mt76/mt7921/init.c | 2 -
.../net/wireless/mediatek/mt76/mt7921/mac.c | 104 +--
.../net/wireless/mediatek/mt76/mt7921/main.c | 26 +-
.../wireless/mediatek/mt76/mt7921/mt7921.h | 9 -
.../net/wireless/mediatek/mt76/mt7921/pci.c | 2 +-
.../wireless/mediatek/mt76/mt7921/pci_mac.c | 16 +-
.../net/wireless/mediatek/mt76/mt7996/init.c | 6 +-
.../net/wireless/mediatek/mt76/mt7996/mac.c | 803 +-----------------
.../net/wireless/mediatek/mt76/mt7996/mac.h | 315 +------
.../net/wireless/mediatek/mt76/mt7996/main.c | 42 +-
.../net/wireless/mediatek/mt76/mt7996/mcu.c | 11 +-
.../wireless/mediatek/mt76/mt7996/mt7996.h | 36 +-
31 files changed, 1403 insertions(+), 1457 deletions(-)
create mode 100644 drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c
create mode 100644 drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h

--
2.40.1



2023-06-09 08:18:57

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 03/15] wifi: mt76: mt7615: rely on shared sta_poll_list and sta_poll_lock

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 <[email protected]>
---
.../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


2023-06-09 08:18:57

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 02/15] wifi: mt76: mt7603: rely on shared sta_poll_list and sta_poll_lock

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 <[email protected]>
---
.../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


2023-06-09 08:18:57

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 09/15] wifi: mt76: mt7996: rely on shared poll_list field

Rely on poll_list field in mt76_wcid structure and get rid of
private copy.

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
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


2023-06-09 08:18:57

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 04/15] wifi: mt76: mt7996: rely on shared sta_poll_list and sta_poll_lock

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 <[email protected]>
---
.../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


2023-06-09 08:18:58

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 05/15] wifi: mt76: mt7921: rely on shared sta_poll_list and sta_poll_lock

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 <[email protected]>
---
.../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


2023-06-09 08:18:58

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 10/15] wifi: mt76: mt7921: rely on shared poll_list field

Rely on poll_list field in mt76_wcid structure and get rid of
private copy.

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
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


2023-06-09 08:18:58

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 11/15] wifi: mt76: move ampdu_state in mt76_wcid

ampdu_state field is used by most of the drivers, so move it in
mt76_wcid structure.

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
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


2023-06-09 08:18:58

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 12/15] mt76: connac: move more mt7921/mt7915 mac shared code in connac lib

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 <[email protected]>
---
.../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


2023-06-09 08:18:58

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 07/15] wifi: mt76: mt7603: rely on shared poll_list field

Rely on poll_list field in mt76_wcid structure and get rid of
private copy.

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
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


2023-06-09 08:18:58

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 13/15] wifi: mt76: move rate info in mt76_vif

This is a preliminary patch to introduce mt76_connac3 mac library used
by WiFi7 chipsets (e.g. mt7996).

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
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


2023-06-09 08:18:58

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 14/15] wifi: mt76: connac: move connac3 definitions in mt76_connac3_mac.h

Connac3 mac definitions are shared between WiFi7 chipsets so move them in
mt76_connac3_mac.h

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
.../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


2023-06-09 08:19:06

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 01/15] wifi: mt76: mt7915: move sta_poll_list and sta_poll_lock in mt76_dev

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 <[email protected]>
---
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


2023-06-09 08:20:00

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 08/15] wifi: mt76: mt7615: rely on shared poll_list field

Rely on poll_list field in mt76_wcid structure and get rid of
private copy.

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
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


2023-06-09 08:20:01

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 06/15] wifi: mt76: mt7915: move poll_list in mt76_wcid

poll_list field is used by most of the drivers, so move it in mt76_wcid
structure.

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
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


2023-06-09 08:20:00

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library

Introduce connac3_mac in mt76_connac library to reuse mac code shared
between WiFi7 chipsets.

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
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


2023-06-09 16:20:38

by Ryder Lee

[permalink] [raw]
Subject: Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library

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 <[email protected]>
> ---
> 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

2023-06-09 16:41:01

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library

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 <[email protected]>
> > ---
> > 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
>


Attachments:
(No filename) (28.75 kB)
signature.asc (235.00 B)
Download all attachments

2023-06-09 16:42:18

by Ryder Lee

[permalink] [raw]
Subject: Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library

On Fri, 2023-06-09 at 18:34 +0200, [email protected] 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 <[email protected]>
> > > ---
> > > 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
> >

2023-06-09 16:44:00

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library

> On Fri, 2023-06-09 at 18:34 +0200, [email protected] 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 <[email protected]>
> > > > ---
> > > > 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
> > >


Attachments:
(No filename) (32.89 kB)
signature.asc (235.00 B)
Download all attachments

2023-06-09 19:17:36

by Shayne Chen

[permalink] [raw]
Subject: Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library

On Sat, 2023-06-10 at 02:47 +0800, Shayne Chen wrote:
> > > On Fri, 2023-06-09 at 18:34 +0200, [email protected]
> >
> > 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 <[email protected]>
>
> Hi Lorenzo,
>
> I don't think it's a good idea to start sharing mac or mcu functions
> for all WiFi7 chipsets at such early stage.
>
> The driver is still under many processes of bug fixing, performance
> tuning, and new features development.
> Chipsets that mainly used for AP or STA segment have different
> designs
> and should face different problems.
>
> Start sharing the code at early stage will break the independence,
> make
> it more hard to develop and do verifications, since many changes will
> affect chipsets of both segments.
>
> Thanks,
> Shayne
>
(Resend for missing CC)

> > > > > > ---
> > > > > > 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_TBL11
> > > > > > +#define MT76_CONNAC3_BEACON_RATES_TBL25
> > > > > >
> > > > >
> > > > > 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
> > > > >

2023-06-10 02:25:28

by Deren Wu

[permalink] [raw]
Subject: Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library

On Fri, 2023-06-09 at 18:45 +0200, [email protected] wrote:
> > On Fri, 2023-06-09 at 18:34 +0200, [email protected]
> > 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 <[email protected]>
> > > > > ---
> > > > > 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
> > > >

2023-06-10 07:57:45

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library

On Jun 10, Deren Wu wrote:
> On Fri, 2023-06-09 at 18:45 +0200, [email protected] wrote:
> > > On Fri, 2023-06-09 at 18:34 +0200, [email protected]
> > > 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 <[email protected]>
> > > > > > ---
> > > > > > 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
> > > > >


Attachments:
(No filename) (38.30 kB)
signature.asc (235.00 B)
Download all attachments

2023-06-10 10:16:27

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library

> On Sat, 2023-06-10 at 02:47 +0800, Shayne Chen wrote:
> > > > On Fri, 2023-06-09 at 18:34 +0200, [email protected]
> > >
> > > 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 <[email protected]>
> >
> > Hi Lorenzo,

Hi Shayne,

> >
> > I don't think it's a good idea to start sharing mac or mcu functions
> > for all WiFi7 chipsets at such early stage.
> >
> > The driver is still under many processes of bug fixing, performance
> > tuning, and new features development.
> > Chipsets that mainly used for AP or STA segment have different
> > designs
> > and should face different problems.
> >
> > Start sharing the code at early stage will break the independence,
> > make
> > it more hard to develop and do verifications, since many changes will
> > affect chipsets of both segments.

my goal is to share the code that hardly will be changed (or that will have
very few changes in the future, i.e. I have not changed mcu codebase).
If you consider for example the routines below:

- mt76_connac*_mac_write_txwi_8023()
- mt76_connac*_mac_write_txwi_80211()
- mt76_connac*_mac_add_txs_skb()
- mt76_connac*_txwi_free()
- ...

they are the same for mt7615/mt7663, mt7921/mt7915, mt7996/.. , what is
changing is just register map between versions (e.g. mt7615/mt7663 and
mt7915/mt7921). I think it is not a good idea to copy-paste the code
because it will just make the code much harder to maintain, and this will be
more difficult to address in the future.
If you consider the commit below:

commit ead449023d3acb1424886d7b8cc672ed69bdd27e
Author: Lorenzo Bianconi <[email protected]>
Date: Sun May 28 12:28:49 2023 +0200

wifi: mt76: mt7996: fix possible NULL pointer dereference in mt7996_mac_write_txwi()

Fix possible NULL pointer dereference on mvif pointer in
mt7996_mac_write_txwi routine.

Deren will needs to monitor the ML and apply the same fix for the other WiFi7
chipset too.

Moreover I kept mt7996/mac.{c,h} to put the per-chipset codebase.
If you think MT76_CONNAC3_BASIC_RATES_TBL11 and MT76_CONNAC3_BEACON_RATES_TBL25
are sensible, we can put them in mt7996/mac.h

Regards,
Lorenzo

> >
> > Thanks,
> > Shayne
> >
> (Resend for missing CC)
>
> > > > > > > ---
> > > > > > > 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_TBL11
> > > > > > > +#define MT76_CONNAC3_BEACON_RATES_TBL25
> > > > > > >
> > > > > >
> > > > > > 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
> > > > > >


Attachments:
(No filename) (40.13 kB)
signature.asc (235.00 B)
Download all attachments

2023-06-10 14:01:32

by Shayne Chen

[permalink] [raw]
Subject: Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library

On Sat, 2023-06-10 at 12:06 +0200, [email protected] wrote:
> > On Sat, 2023-06-10 at 02:47 +0800, Shayne Chen wrote:
> > > > > On Fri, 2023-06-09 at 18:34 +0200,
> > > > > [email protected]
> > > >
> > > > 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 <[email protected]>
> > >
> > > Hi Lorenzo,
>
> Hi Shayne,
>
Hi Lorenzo,

> > >
> > > I don't think it's a good idea to start sharing mac or mcu
> > > functions
> > > for all WiFi7 chipsets at such early stage.
> > >
> > > The driver is still under many processes of bug fixing,
> > > performance
> > > tuning, and new features development.
> > > Chipsets that mainly used for AP or STA segment have different
> > > designs
> > > and should face different problems.
> > >
> > > Start sharing the code at early stage will break the
> > > independence,
> > > make
> > > it more hard to develop and do verifications, since many changes
> > > will
> > > affect chipsets of both segments.
>
> my goal is to share the code that hardly will be changed (or that
> will have
> very few changes in the future, i.e. I have not changed mcu
> codebase).
> If you consider for example the routines below:
>
> - mt76_connac*_mac_write_txwi_8023()
> - mt76_connac*_mac_write_txwi_80211()
> - mt76_connac*_mac_add_txs_skb()
> - mt76_connac*_txwi_free()
> - ...
>
> they are the same for mt7615/mt7663, mt7921/mt7915, mt7996/.. , what
> is
> changing is just register map between versions (e.g. mt7615/mt7663
> and
> mt7915/mt7921). I think it is not a good idea to copy-paste the code
> because it will just make the code much harder to maintain, and this
> will be
> more difficult to address in the future.
> If you consider the commit below:
>
> commit ead449023d3acb1424886d7b8cc672ed69bdd27e
> Author: Lorenzo Bianconi <[email protected]>
> Date: Sun May 28 12:28:49 2023 +0200
>
> wifi: mt76: mt7996: fix possible NULL pointer dereference in
> mt7996_mac_write_txwi()
>
> Fix possible NULL pointer dereference on mvif pointer in
> mt7996_mac_write_txwi routine.
>
> Deren will needs to monitor the ML and apply the same fix for the
> other WiFi7
> chipset too.
>
> Moreover I kept mt7996/mac.{c,h} to put the per-chipset codebase.
> If you think MT76_CONNAC3_BASIC_RATES_TBL11 and
> MT76_CONNAC3_BEACON_RATES_TBL25
> are sensible, we can put them in mt7996/mac.h

I understand your concern, but if the code starts to be shared at early
stage, we may need to add several is_mt7996() to split different parts
temporarily or permanently, since we have different development
procedure and focusing, on devices of different segements.

Below are some examples I concern:
- We're doing some tests about switching all TXS to PPDU TXS, and the
code in mac_add_txs_skb() needs to be changed. If devices of STA
segement don't want to change or won't switch in short time, we may
need to add is_mt7996() to split.

- When adding MLO support, there will be many changes in
mac_write_txwi() and txwi_free(), compared to previous chipsets. To
prevent from adding side effects to other devices, we may also need to
add is_mt7996() to split code at least for temporary.

I would like to know is it fine with you to add some is_mt7996() to the
shared code for the above examples?
I think this could help to balance the trade off between sharing code
and assuring the driver stability on different segements.

Thanks,
Shayne

>
> Regards,
> Lorenzo
>
> > >
> > > Thanks,
> > > Shayne
> > >
> >
> > (Resend for missing CC)
> >
> > > > > > > > ---
> > > > > > > > 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_TBL11
> > > > > > > > +#define MT76_CONNAC3_BEACON_RATES_TBL25
> > > > > > > >
> > > > > > >
> > > > > > > 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
> > > > > > >

2023-06-10 15:08:54

by Ryder Lee

[permalink] [raw]
Subject: Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library

On Sat, 2023-06-10 at 13:49 +0000, Shayne Chen (陳軒丞) wrote:
> On Sat, 2023-06-10 at 12:06 +0200, [email protected] wrote:
> > > On Sat, 2023-06-10 at 02:47 +0800, Shayne Chen wrote:
> > > > > > On Fri, 2023-06-09 at 18:34 +0200,
> > > > > > [email protected]
> > > > >
> > > > > 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 <[email protected]>
> > > >
> > > > Hi Lorenzo,
> >
> > Hi Shayne,
> >
>
> Hi Lorenzo,
>
> > > >
> > > > I don't think it's a good idea to start sharing mac or mcu
> > > > functions
> > > > for all WiFi7 chipsets at such early stage.
> > > >
> > > > The driver is still under many processes of bug fixing,
> > > > performance
> > > > tuning, and new features development.
> > > > Chipsets that mainly used for AP or STA segment have different
> > > > designs
> > > > and should face different problems.
> > > >
> > > > Start sharing the code at early stage will break the
> > > > independence,
> > > > make
> > > > it more hard to develop and do verifications, since many
> > > > changes
> > > > will
> > > > affect chipsets of both segments.
> >
> > my goal is to share the code that hardly will be changed (or that
> > will have
> > very few changes in the future, i.e. I have not changed mcu
> > codebase).
> > If you consider for example the routines below:
> >
> > - mt76_connac*_mac_write_txwi_8023()
> > - mt76_connac*_mac_write_txwi_80211()
> > - mt76_connac*_mac_add_txs_skb()
> > - mt76_connac*_txwi_free()
> > - ...
> >
> > they are the same for mt7615/mt7663, mt7921/mt7915, mt7996/.. ,
> > what
> > is
> > changing is just register map between versions (e.g. mt7615/mt7663
> > and
> > mt7915/mt7921). I think it is not a good idea to copy-paste the
> > code
> > because it will just make the code much harder to maintain, and
> > this
> > will be
> > more difficult to address in the future.
> > If you consider the commit below:
> >
> > commit ead449023d3acb1424886d7b8cc672ed69bdd27e
> > Author: Lorenzo Bianconi <[email protected]>
> > Date: Sun May 28 12:28:49 2023 +0200
> >
> > wifi: mt76: mt7996: fix possible NULL pointer dereference in
> > mt7996_mac_write_txwi()
> >
> > Fix possible NULL pointer dereference on mvif pointer in
> > mt7996_mac_write_txwi routine.
> >
> > Deren will needs to monitor the ML and apply the same fix for the
> > other WiFi7
> > chipset too.
> >
This depends on viewpoint. For instance, I planed to add many changes
for mt7986 but 7921 doesn't use (or even don't care), but I need to
check other don't care devices without any help (because they don't
care), so we maintain more an more patches in local branch rather than
upstreming.

Other that that, I think it's ok in wifi6 but wifi7 is REALLY
different. it's better to wait the major MLO development finished to
have a whole picture to know what the best way to unify.

> > Moreover I kept mt7996/mac.{c,h} to put the per-chipset codebase.
> > If you think MT76_CONNAC3_BASIC_RATES_TBL11 and
> > MT76_CONNAC3_BEACON_RATES_TBL25
> > are sensible, we can put them in mt7996/mac.h
>

and this is just one anther example I can tell right now.

> I understand your concern, but if the code starts to be shared at
> early
> stage, we may need to add several is_mt7996() to split different
> parts
> temporarily or permanently, since we have different development
> procedure and focusing, on devices of different segements.
>
> Below are some examples I concern:
> - We're doing some tests about switching all TXS to PPDU TXS, and the
> code in mac_add_txs_skb() needs to be changed. If devices of STA
> segement don't want to change or won't switch in short time, we may
> need to add is_mt7996() to split.
>
> - When adding MLO support, there will be many changes in
> mac_write_txwi() and txwi_free(), compared to previous chipsets. To
> prevent from adding side effects to other devices, we may also need
> to
> add is_mt7996() to split code at least for temporary.
>
> I would like to know is it fine with you to add some is_mt7996() to
> the
> shared code for the above examples?
> I think this could help to balance the trade off between sharing code
> and assuring the driver stability on different segements.
>
> Thanks,
> Shayne
> > > > > > > > >

2023-06-12 09:26:19

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library

"[email protected]" <[email protected]> writes:

> On Jun 10, Deren Wu wrote:
>> On Fri, 2023-06-09 at 18:45 +0200, [email protected] wrote:
>> > > On Fri, 2023-06-09 at 18:34 +0200, [email protected]
>> > > 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