blob: f185feda57c6c173df6929ca393122801426dcde [file] [log] [blame]
developer05f3b2b2024-08-19 19:17:34 +08001From ac20b6e9a96c45213a2bbccb051d16e4408f2969 Mon Sep 17 00:00:00 2001
2From: Rex Lu <rex.lu@mediatek.com>
3Date: Fri, 7 Jun 2024 13:51:25 +0800
4Subject: [PATCH 150/199] mtk: mt76: mt7996: Fix inconsistent QoS mapping
5 between SW and HW
6
7Fix inconsistent QoS mapping between SW and HW.
8Specifically, the mapping from IP DSCP to IEEE 802.11 user priority may be customized.
9Therefore, driver needs to pass the mapping to HW, so that the QoS type of traffic can be mapped in a consistent manner for both SW and HW paths.
10
11Refactor mt7996_mcu_set_qos_map function.
121. According to fw logic, it will fill the dscp value 0~63 correspond tid.
13for example:
14The last set is 48-56 in the default qos map from hostapd.
15And it will set tid 7. but 57-63 in original function will not fill any value,
16so it will set zero to fw. Once the value of dscp is 57. mac80211 will correspond to tid 7.
17and fw will correspond to tid 0.
18
19Signed-off-by: Benjamin Lin <benjamin-jw.lin@mediatek.com>
20Signed-off-by: Rex Lu <rex.lu@mediatek.com>
21---
22 mt76_connac_mcu.h | 1 +
23 mt7996/main.c | 31 ++++++++++++++++++++++++++
24 mt7996/mcu.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++
25 mt7996/mt7996.h | 8 ++++++-
26 4 files changed, 94 insertions(+), 1 deletion(-)
27
28diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
29index f7b1f0d0..0244b5aa 100644
30--- a/mt76_connac_mcu.h
31+++ b/mt76_connac_mcu.h
32@@ -1262,6 +1262,7 @@ enum {
33 MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab,
34 MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac,
35 MCU_EXT_CMD_PHY_STAT_INFO = 0xad,
36+ MCU_EXT_CMD_SET_QOS_MAP = 0xb4,
37 };
38
39 enum {
40diff --git a/mt7996/main.c b/mt7996/main.c
41index b6231dff..3c12bd52 100644
42--- a/mt7996/main.c
43+++ b/mt7996/main.c
44@@ -2365,6 +2365,9 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
45
46 ctx->dev = NULL;
47
48+ if (path->mtk_wdma.amsdu)
49+ path->mtk_wdma.tid = mvif->qos_map[path->mtk_wdma.tid >> 2];
50+
51 return 0;
52 }
53
54@@ -2794,6 +2797,33 @@ mt7996_event_callback(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
55 }
56 }
57
58+static int
59+mt7996_set_qos_map(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
60+ struct cfg80211_qos_map *qos_map)
61+{
62+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
63+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
64+ unsigned long valid_links = vif->valid_links ?: BIT(0);
65+ unsigned int link_id;
66+ int ret = 0;
67+
68+ mutex_lock(&dev->mt76.mutex);
69+ for_each_set_bit(link_id, &valid_links, IEEE80211_MLD_MAX_NUM_LINKS) {
70+ struct mt7996_bss_conf *mconf =
71+ mconf_dereference_protected(mvif, link_id);
72+
73+ if (!mconf)
74+ continue;
75+
76+ ret = mt7996_mcu_set_qos_map(dev, mconf, qos_map);
77+ if(ret)
78+ break;
79+ }
80+ mutex_unlock(&dev->mt76.mutex);
81+
82+ return ret;
83+}
84+
85 const struct ieee80211_ops mt7996_ops = {
86 .add_chanctx = ieee80211_emulate_add_chanctx,
87 .remove_chanctx = ieee80211_emulate_remove_chanctx,
88@@ -2861,4 +2891,5 @@ const struct ieee80211_ops mt7996_ops = {
89 .switch_vif_chanctx = mt7996_switch_vif_chanctx,
90 .change_vif_links = mt7996_change_vif_links,
91 .change_sta_links = mt7996_change_sta_links,
92+ .set_qos_map = mt7996_set_qos_map,
93 };
94diff --git a/mt7996/mcu.c b/mt7996/mcu.c
95index db388e66..51f15928 100644
96--- a/mt7996/mcu.c
97+++ b/mt7996/mcu.c
98@@ -6667,4 +6667,59 @@ int mt7996_mcu_set_csi(struct mt7996_phy *phy, u8 mode,
99 return -EINVAL;
100 }
101 }
102+
103+int mt7996_mcu_set_qos_map(struct mt7996_dev *dev, struct mt7996_bss_conf *mconf,
104+ struct cfg80211_qos_map *usr_qos_map)
105+{
106+ struct {
107+ u8 bss_idx;
108+ u8 qos_map_enable;
109+ u8 __rsv[2];
110+ s8 qos_map[IP_DSCP_NUM];
111+ } __packed req = {
112+ .bss_idx = mconf->mt76.idx,
113+ .qos_map_enable = true,
114+ };
115+ s8 i;
116+
117+ /* Default QoS map, defined in section 2.3 of RFC8325.
118+ * Three most significant bits of DSCP are used as UP.
119+ */
120+ for (i = 0; i < IP_DSCP_NUM; ++i)
121+ req.qos_map[i] = i >> 3;
122+
123+ /* Recommended QoS map, defined in section 4 of RFC8325.
124+ * Used in cfg80211_classify8021d since kernel v6.8.
125+ */
126+ req.qos_map[10] = req.qos_map[12] = req.qos_map[14] = req.qos_map[16] = 0;
127+ req.qos_map[18] = req.qos_map[20] = req.qos_map[22] = 3;
128+ req.qos_map[24] = 4;
129+ req.qos_map[40] = 5;
130+ req.qos_map[44] = req.qos_map[46] = 6;
131+ req.qos_map[48] = 7;
132+
133+ /* User-defined QoS map */
134+ if (usr_qos_map) {
135+ for (i = 0; i < IEEE80211_NUM_UPS; ++i) {
136+ u8 low = usr_qos_map->up[i].low;
137+ u8 high = usr_qos_map->up[i].high;
138+
139+ if (low < IP_DSCP_NUM && high < IP_DSCP_NUM && low <= high)
140+ memset(req.qos_map + low, i, high - low + 1);
141+ }
142+
143+ for (i = 0; i < usr_qos_map->num_des; ++i) {
144+ u8 dscp = usr_qos_map->dscp_exception[i].dscp;
145+ u8 up = usr_qos_map->dscp_exception[i].up;
146+
147+ if (dscp < IP_DSCP_NUM && up < IEEE80211_NUM_UPS)
148+ req.qos_map[dscp] = up;
149+ }
150+ }
151+
152+ memcpy(mconf->vif->qos_map, req.qos_map, IP_DSCP_NUM);
153+
154+ return mt76_mcu_send_msg(&dev->mt76, MCU_WA_EXT_CMD(SET_QOS_MAP), &req,
155+ sizeof(req), false);
156+}
157 #endif
158diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
159index dc0209de..302ac7bf 100644
160--- a/mt7996/mt7996.h
161+++ b/mt7996/mt7996.h
162@@ -134,6 +134,8 @@
163 #define MT7996_MAX_PROBE_TIMEOUT 500
164 #define MT7996_MAX_PROBE_TRIES 2
165
166+#define IP_DSCP_NUM 64
167+
168 struct mt7996_vif;
169 struct mt7996_sta;
170 struct mt7996_dfs_pulse;
171@@ -376,6 +378,9 @@ struct mt7996_vif {
172 void *probe[__MT_MAX_BAND];
173 unsigned long probe_send_time[__MT_MAX_BAND];
174 int probe_send_count[__MT_MAX_BAND];
175+
176+ /* QoS map support */
177+ u8 qos_map[IP_DSCP_NUM];
178 };
179
180 /* crash-dump */
181@@ -1333,5 +1338,6 @@ int mt7996_mcu_mlo_agc(struct mt7996_dev *dev, const void *data, int len);
182 #ifdef CONFIG_NET_MEDIATEK_SOC_WED
183 int mt7996_dma_rro_init(struct mt7996_dev *dev);
184 #endif /* CONFIG_NET_MEDIATEK_SOC_WED */
185-
186+int mt7996_mcu_set_qos_map(struct mt7996_dev *dev, struct mt7996_bss_conf *mconf,
187+ struct cfg80211_qos_map *usr_qos_map);
188 #endif
189--
1902.18.0
191