Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

wifi: mt76: connac: rework TX descriptor and TX free for mt7990

Adjust the TX descriptor and TX free for updated hardware fields.
This is a preliminary patch to support mt7990 chipset.

Co-developed-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Co-developed-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
Co-developed-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Link: https://patch.msgid.link/20250409140750.724437-9-shayne.chen@mediatek.com
Signed-off-by: Felix Fietkau <nbd@nbd.name>

authored by

Shayne Chen and committed by
Felix Fietkau
b7ddeb9c 6d72f267

+37 -6
+1
drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h
··· 273 273 #define MT_TXD6_TX_RATE GENMASK(21, 16) 274 274 #define MT_TXD6_TIMESTAMP_OFS_EN BIT(15) 275 275 #define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10) 276 + #define MT_TXD6_TID_ADDBA GENMASK(10, 8) 276 277 #define MT_TXD6_MSDU_CNT GENMASK(9, 4) 277 278 #define MT_TXD6_MSDU_CNT_V2 GENMASK(15, 10) 278 279 #define MT_TXD6_DIS_MAT BIT(3)
+36 -6
drivers/net/wireless/mediatek/mt76/mt7996/mac.c
··· 789 789 790 790 if (ieee80211_is_action(fc) && 791 791 mgmt->u.action.category == WLAN_CATEGORY_BACK && 792 - mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) 792 + mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) { 793 + if (is_mt7990(&dev->mt76)) 794 + txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TID_ADDBA, tid)); 793 795 tid = MT_TX_ADDBA; 794 - else if (ieee80211_is_mgmt(hdr->frame_control)) 796 + } else if (ieee80211_is_mgmt(hdr->frame_control)) { 795 797 tid = MT_TX_NORMAL; 798 + } 796 799 797 800 val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | 798 801 FIELD_PREP(MT_TXD1_HDR_INFO, ··· 990 987 } 991 988 } 992 989 990 + static bool 991 + mt7996_tx_use_mgmt(struct mt7996_dev *dev, struct sk_buff *skb) 992 + { 993 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 994 + 995 + if (ieee80211_is_mgmt(hdr->frame_control)) 996 + return true; 997 + 998 + /* for SDO to bypass specific data frame */ 999 + if (!mt7996_has_wa(dev)) { 1000 + if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))) 1001 + return true; 1002 + 1003 + if (ieee80211_has_a4(hdr->frame_control) && 1004 + !ieee80211_is_data_present(hdr->frame_control)) 1005 + return true; 1006 + } 1007 + 1008 + return false; 1009 + } 1010 + 993 1011 int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, 994 1012 enum mt76_txq_id qid, struct mt76_wcid *wcid, 995 1013 struct ieee80211_sta *sta, 996 1014 struct mt76_tx_info *tx_info) 997 1015 { 998 - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; 999 1016 struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); 1000 1017 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); 1001 1018 struct ieee80211_key_conf *key = info->control.hw_key; ··· 1064 1041 if (!key) 1065 1042 txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); 1066 1043 1067 - if (!is_8023 && ieee80211_is_mgmt(hdr->frame_control)) 1044 + if (!is_8023 && mt7996_tx_use_mgmt(dev, tx_info->skb)) 1068 1045 txp->fw.flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); 1069 1046 1070 1047 if (vif) { ··· 1202 1179 void *end = data + len; 1203 1180 bool wake = false; 1204 1181 u16 total, count = 0; 1182 + u8 ver; 1205 1183 1206 1184 /* clean DMA queues and unmap buffers first */ 1207 1185 mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); ··· 1216 1192 mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_BE], false); 1217 1193 } 1218 1194 1219 - if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 5)) 1195 + ver = le32_get_bits(tx_free[1], MT_TXFREE1_VER); 1196 + if (WARN_ON_ONCE(ver < 5)) 1220 1197 return; 1221 1198 1222 1199 total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT); ··· 1239 1214 wcid = rcu_dereference(dev->mt76.wcid[idx]); 1240 1215 sta = wcid_to_sta(wcid); 1241 1216 if (!sta) 1242 - continue; 1217 + goto next; 1243 1218 1244 1219 msta_link = container_of(wcid, struct mt7996_sta_link, 1245 1220 wcid); 1246 1221 mt76_wcid_add_poll(&dev->mt76, &msta_link->wcid); 1222 + next: 1223 + /* ver 7 has a new DW with pair = 1, skip it */ 1224 + if (ver == 7 && ((void *)(cur_info + 1) < end) && 1225 + (le32_to_cpu(*(cur_info + 1)) & MT_TXFREE_INFO_PAIR)) 1226 + cur_info++; 1247 1227 continue; 1248 1228 } else if (info & MT_TXFREE_INFO_HEADER) { 1249 1229 u32 tx_retries = 0, tx_failed = 0;