blob: efe816ccf14ebc896d6d0989a0b800375bf7d200 [file] [log] [blame]
developer66e89bc2024-04-23 14:50:01 +08001From fa5c84eb945cb472d98172876d176bff4a082d67 Mon Sep 17 00:00:00 2001
2From: Shayne Chen <shayne.chen@mediatek.com>
3Date: Mon, 6 Nov 2023 16:17:11 +0800
4Subject: [PATCH 084/116] wifi: mt76: mt7996: implement and switch to chanctx
5 callbacks
6
7To support MLO, chanctx callbacks are mandatory, since one VIF (MLD) could
8operate on multiple channels (links).
9This is a preliminary patch to add MLO support for mt7996 chipsets.
10
11Change-Id: Ie4530a3bc2ac9e51045184d5aecca14118177042
12Co-developed-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
13Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
14Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
15---
16 mt7996/init.c | 22 ++++++
17 mt7996/mac.c | 10 ++-
18 mt7996/main.c | 178 ++++++++++++++++++++++++++++++++++++++++++++----
19 mt7996/mcu.c | 2 +-
20 mt7996/mt7996.h | 17 +++++
21 5 files changed, 211 insertions(+), 18 deletions(-)
22
23diff --git a/mt7996/init.c b/mt7996/init.c
24index 952356823..6eeec3b8d 100644
25--- a/mt7996/init.c
26+++ b/mt7996/init.c
27@@ -382,6 +382,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
28
29 hw->sta_data_size = sizeof(struct mt7996_sta);
30 hw->vif_data_size = sizeof(struct mt7996_vif);
31+ hw->chanctx_data_size = sizeof(struct mt7996_chanctx);
32
33 wiphy->iface_combinations = if_comb;
34 wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
35@@ -417,6 +418,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
36 ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
37 ieee80211_hw_set(hw, WANT_MONITOR_VIF);
38 ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
39+ ieee80211_hw_set(hw, CHANCTX_STA_CSA);
40
41 hw->max_tx_fragments = 4;
42
43@@ -637,6 +639,22 @@ static int mt7996_vow_init(struct mt7996_phy *phy)
44 return mt7996_mcu_set_vow_feature_ctrl(phy);
45 }
46
47+static void mt7996_init_chanctx(struct mt7996_phy *phy)
48+{
49+ struct ieee80211_supported_band *sband;
50+ struct ieee80211_channel *chan;
51+
52+ if (phy->mt76->band_idx == MT_BAND2)
53+ sband = &phy->mt76->sband_6g.sband;
54+ else if (phy->mt76->band_idx == MT_BAND1)
55+ sband = &phy->mt76->sband_5g.sband;
56+ else
57+ sband = &phy->mt76->sband_2g.sband;
58+
59+ chan = &sband->channels[0];
60+ cfg80211_chandef_create(&phy->mt76->chandef, chan, NL80211_CHAN_HT20);
61+}
62+
63 static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
64 enum mt76_band_id band)
65 {
66@@ -720,6 +738,8 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
67 if (ret)
68 goto error;
69
70+ mt7996_init_chanctx(phy);
71+
72 ret = mt7996_thermal_init(phy);
73 if (ret)
74 goto error;
75@@ -1609,6 +1629,8 @@ int mt7996_register_device(struct mt7996_dev *dev)
76 if (ret)
77 return ret;
78
79+ mt7996_init_chanctx(&dev->phy);
80+
81 ret = mt7996_thermal_init(&dev->phy);
82 if (ret)
83 return ret;
84diff --git a/mt7996/mac.c b/mt7996/mac.c
85index 4e9dd2c1f..0879c7735 100644
86--- a/mt7996/mac.c
87+++ b/mt7996/mac.c
88@@ -2785,7 +2785,10 @@ void mt7996_scan_work(struct work_struct *work)
89 mt7996_scan_complete(phy, false);
90 mutex_unlock(&phy->dev->mt76.mutex);
91
92- mt7996_set_channel(phy, &hw->conf.chandef);
93+ if (phy->chanctx)
94+ mt7996_set_channel(phy, &phy->chanctx->chandef);
95+ else
96+ mt7996_set_channel(phy, &phy->mt76->chandef);
97
98 return;
99 }
100@@ -2797,7 +2800,10 @@ void mt7996_scan_work(struct work_struct *work)
101 phy->scan_chan = NULL;
102 mutex_unlock(&phy->dev->mt76.mutex);
103
104- mt7996_set_channel(phy, &phy->mt76->chandef);
105+ if (phy->chanctx)
106+ mt7996_set_channel(phy, &phy->chanctx->chandef);
107+ else
108+ mt7996_set_channel(phy, &phy->mt76->chandef);
109
110 ieee80211_queue_delayed_work(hw, &phy->scan_work, HZ / 10);
111
112diff --git a/mt7996/main.c b/mt7996/main.c
113index c8f1b1097..dd4f3a711 100644
114--- a/mt7996/main.c
115+++ b/mt7996/main.c
116@@ -76,6 +76,11 @@ int mt7996_run(struct ieee80211_hw *hw)
117 if (ret)
118 goto out;
119
120+ /* set a parking channel */
121+ ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH);
122+ if (ret)
123+ goto out;
124+
125 ret = mt7996_mcu_set_thermal_throttling(phy, MT7996_THERMAL_THROTTLE_MAX);
126 if (ret)
127 goto out;
128@@ -510,21 +515,6 @@ static int mt7996_config(struct ieee80211_hw *hw, u32 changed)
129 struct mt7996_phy *phy = mt7996_hw_phy(hw);
130 int ret;
131
132- if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
133- if (!mt76_testmode_enabled(phy->mt76) && !phy->mt76->test.bf_en) {
134- ret = mt7996_mcu_edcca_enable(phy, true);
135- if (ret)
136- return ret;
137- }
138-
139- ret = mt7996_mcu_set_pp_en(phy, PP_USR_MODE,
140- phy->mt76->chandef.punctured);
141- if (ret)
142- return ret;
143-
144- mt7996_set_channel(phy, &hw->conf.chandef);
145- }
146-
147 if (changed & (IEEE80211_CONF_CHANGE_POWER |
148 IEEE80211_CONF_CHANGE_CHANNEL)) {
149 ret = mt7996_mcu_set_txpower_sku(phy);
150@@ -1725,6 +1715,158 @@ mt7996_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
151 mutex_unlock(&phy->dev->mt76.mutex);
152 }
153
154+static int
155+mt7996_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *conf)
156+{
157+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
158+ struct mt7996_chanctx *ctx = mt7996_chanctx_get(conf);
159+ int ret;
160+
161+ wiphy_info(hw->wiphy, "%s: add %u\n", __func__, conf->def.chan->hw_value);
162+ mutex_lock(&phy->dev->mt76.mutex);
163+
164+ if (ctx->assigned) {
165+ mutex_unlock(&phy->dev->mt76.mutex);
166+ return -ENOSPC;
167+ }
168+
169+ ctx->assigned = true;
170+ ctx->chandef = conf->def;
171+ ctx->phy = phy;
172+ if (phy->chanctx) {
173+ mutex_unlock(&phy->dev->mt76.mutex);
174+ return 0;
175+ }
176+
177+ phy->chanctx = ctx;
178+ mutex_unlock(&phy->dev->mt76.mutex);
179+
180+ if (!mt76_testmode_enabled(phy->mt76) && !phy->mt76->test.bf_en) {
181+ ret = mt7996_mcu_edcca_enable(phy, true);
182+ if (ret)
183+ return ret;
184+ }
185+
186+ ret = mt7996_mcu_set_pp_en(phy, PP_USR_MODE, ctx->chandef.punctured);
187+ if (ret)
188+ return ret;
189+
190+ return mt7996_set_channel(phy, &ctx->chandef);
191+}
192+
193+static void
194+mt7996_remove_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *conf)
195+{
196+ struct mt7996_chanctx *ctx = mt7996_chanctx_get(conf);
197+ struct mt7996_phy *phy = ctx->phy;
198+
199+ wiphy_info(hw->wiphy, "%s: remove %u\n", __func__, conf->def.chan->hw_value);
200+ cancel_delayed_work_sync(&phy->scan_work);
201+ cancel_delayed_work_sync(&phy->mt76->mac_work);
202+
203+ mutex_lock(&phy->dev->mt76.mutex);
204+ ctx->assigned = false;
205+ if (ctx == phy->chanctx)
206+ phy->chanctx = NULL;
207+ mutex_unlock(&phy->dev->mt76.mutex);
208+}
209+
210+static void
211+mt7996_change_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *conf,
212+ u32 changed)
213+{
214+ struct mt7996_chanctx *ctx = mt7996_chanctx_get(conf);
215+ struct mt7996_phy *phy = ctx->phy;
216+
217+ wiphy_info(hw->wiphy, "%s: change %u, 0x%x\n", __func__, conf->def.chan->hw_value, changed);
218+ if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) {
219+ ctx->chandef = conf->def;
220+
221+ mt7996_set_channel(phy, &ctx->chandef);
222+ }
223+}
224+
225+static int
226+mt7996_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
227+ struct ieee80211_bss_conf *link_conf,
228+ struct ieee80211_chanctx_conf *conf)
229+{
230+ struct mt7996_chanctx *ctx = mt7996_chanctx_get(conf);
231+ struct mt7996_phy *phy = ctx->phy;
232+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
233+
234+ wiphy_info(hw->wiphy, "Assign VIF (addr: %pM, type: %d, link_id: %d) to channel context: %d MHz\n",
235+ vif->addr, vif->type, link_conf->link_id,
236+ conf->def.chan->center_freq);
237+
238+ mutex_lock(&phy->dev->mt76.mutex);
239+
240+ mvif->chanctx = ctx;
241+ ctx->nbss_assigned++;
242+
243+ mutex_unlock(&phy->dev->mt76.mutex);
244+
245+ return 0;
246+}
247+
248+static void
249+mt7996_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
250+ struct ieee80211_bss_conf *link_conf,
251+ struct ieee80211_chanctx_conf *conf)
252+{
253+ struct mt7996_chanctx *ctx = mt7996_chanctx_get(conf);
254+ struct mt7996_phy *phy = ctx->phy;
255+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
256+
257+ wiphy_info(hw->wiphy, "Remove VIF (addr: %pM, type: %d, link_id: %d) from channel context: %d MHz\n",
258+ vif->addr, vif->type, link_conf->link_id,
259+ conf->def.chan->center_freq);
260+ cancel_delayed_work_sync(&phy->scan_work);
261+
262+ mutex_lock(&phy->dev->mt76.mutex);
263+
264+ if (test_bit(MT76_SCANNING, &phy->mt76->state))
265+ mt7996_scan_complete(phy, true);
266+
267+ mvif->chanctx = NULL;
268+ ctx->nbss_assigned--;
269+
270+ mutex_unlock(&phy->dev->mt76.mutex);
271+}
272+
273+static int
274+mt7996_switch_vif_chanctx(struct ieee80211_hw *hw,
275+ struct ieee80211_vif_chanctx_switch *vifs,
276+ int n_vifs,
277+ enum ieee80211_chanctx_switch_mode mode)
278+{
279+ struct mt7996_chanctx *old_ctx = mt7996_chanctx_get(vifs->old_ctx);
280+ struct mt7996_chanctx *new_ctx = mt7996_chanctx_get(vifs->new_ctx);
281+ struct mt7996_phy *phy = old_ctx->phy;
282+
283+ wiphy_info(hw->wiphy, "%s: old=%d, new=%d\n", __func__, vifs->old_ctx->def.chan->hw_value, vifs->new_ctx->def.chan->hw_value);
284+
285+ if (new_ctx->nbss_assigned && phy->chanctx == new_ctx) {
286+ new_ctx->nbss_assigned += n_vifs;
287+ return 0;
288+ }
289+
290+ if (WARN_ON(old_ctx != phy->chanctx))
291+ return -EINVAL;
292+
293+ mutex_lock(&phy->dev->mt76.mutex);
294+
295+ phy->chanctx = new_ctx;
296+ new_ctx->assigned = true;
297+ new_ctx->chandef = vifs->new_ctx->def;
298+ new_ctx->phy = phy;
299+ new_ctx->nbss_assigned += n_vifs;
300+
301+ mutex_unlock(&phy->dev->mt76.mutex);
302+
303+ return mt7996_set_channel(phy, &new_ctx->chandef);
304+}
305+
306 const struct ieee80211_ops mt7996_ops = {
307 .tx = mt7996_tx,
308 .start = mt7996_start,
309@@ -1775,4 +1917,10 @@ const struct ieee80211_ops mt7996_ops = {
310 .net_fill_forward_path = mt7996_net_fill_forward_path,
311 .net_setup_tc = mt76_wed_net_setup_tc,
312 #endif
313+ .add_chanctx = mt7996_add_chanctx,
314+ .remove_chanctx = mt7996_remove_chanctx,
315+ .change_chanctx = mt7996_change_chanctx,
316+ .assign_vif_chanctx = mt7996_assign_vif_chanctx,
317+ .unassign_vif_chanctx = mt7996_unassign_vif_chanctx,
318+ .switch_vif_chanctx = mt7996_switch_vif_chanctx,
319 };
320diff --git a/mt7996/mcu.c b/mt7996/mcu.c
321index 99cca0dc7..85077108e 100644
322--- a/mt7996/mcu.c
323+++ b/mt7996/mcu.c
324@@ -5309,7 +5309,7 @@ int mt7996_mcu_set_pp_en(struct mt7996_phy *phy, u8 mode, u16 bitmap)
325 .bitmap = cpu_to_le16(bitmap),
326 };
327
328- if (phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ ||
329+ if (phy->chanctx->chandef.chan->band == NL80211_BAND_2GHZ ||
330 mode > PP_USR_MODE)
331 return 0;
332
333diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
334index fbf1e835b..84aafb404 100644
335--- a/mt7996/mt7996.h
336+++ b/mt7996/mt7996.h
337@@ -332,6 +332,8 @@ struct mt7996_vif {
338
339 struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
340 struct cfg80211_bitrate_mask bitrate_mask;
341+
342+ struct mt7996_chanctx *chanctx;
343 };
344
345 /* crash-dump */
346@@ -421,6 +423,14 @@ struct mt7996_rro_ba_session {
347 u32 last_in_rxtime :12;
348 };
349
350+struct mt7996_chanctx {
351+ struct cfg80211_chan_def chandef;
352+ struct mt7996_phy *phy;
353+
354+ bool assigned;
355+ u8 nbss_assigned;
356+};
357+
358 struct mt7996_phy {
359 struct mt76_phy *mt76;
360 struct mt7996_dev *dev;
361@@ -464,6 +474,7 @@ struct mt7996_phy {
362 struct cfg80211_scan_request *scan_req;
363 struct ieee80211_vif *scan_vif;
364 int scan_chan_idx;
365+ struct mt7996_chanctx *chanctx;
366
367 struct mt7996_scs_ctrl scs_ctrl;
368 u32 red_drop;
369@@ -752,6 +763,12 @@ mt7996_get_background_radar_cap(struct mt7996_dev *dev)
370 return 1;
371 }
372
373+static inline struct mt7996_chanctx *
374+mt7996_chanctx_get(struct ieee80211_chanctx_conf *ctx)
375+{
376+ return (struct mt7996_chanctx *)&ctx->drv_priv;
377+}
378+
379 extern const struct ieee80211_ops mt7996_ops;
380 extern struct pci_driver mt7996_pci_driver;
381 extern struct pci_driver mt7996_hif_driver;
382--
3832.39.2
384