xref: /linux/drivers/net/wireless/mediatek/mt76/channel.c (revision 3049a7f210adaa633e834a7e9e0fd3c6cf8600b4)
1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3  * Copyright (C) 2024 Felix Fietkau <nbd@nbd.name>
4  */
5 #include "mt76.h"
6 
7 static struct mt76_vif_link *
8 mt76_alloc_mlink(struct mt76_dev *dev, struct mt76_vif_data *mvif)
9 {
10 	struct mt76_vif_link *mlink;
11 
12 	mlink = kzalloc(dev->drv->link_data_size, GFP_KERNEL);
13 	if (!mlink)
14 		return NULL;
15 
16 	mlink->mvif = mvif;
17 
18 	return mlink;
19 }
20 
21 static int
22 mt76_phy_update_channel(struct mt76_phy *phy,
23 			struct ieee80211_chanctx_conf *conf)
24 {
25 	phy->radar_enabled = conf->radar_enabled;
26 	phy->main_chandef = conf->def;
27 	phy->chanctx = (struct mt76_chanctx *)conf->drv_priv;
28 
29 	return __mt76_set_channel(phy, &phy->main_chandef, false);
30 }
31 
32 int mt76_add_chanctx(struct ieee80211_hw *hw,
33 		     struct ieee80211_chanctx_conf *conf)
34 {
35 	struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv;
36 	struct mt76_phy *phy = hw->priv;
37 	struct mt76_dev *dev = phy->dev;
38 	int ret = -EINVAL;
39 
40 	phy = ctx->phy = dev->band_phys[conf->def.chan->band];
41 	if (WARN_ON_ONCE(!phy))
42 		return ret;
43 
44 	if (mt76_phy_scanning(phy))
45 		mt76_abort_scan(dev);
46 
47 	mutex_lock(&dev->mutex);
48 	if (!phy->chanctx)
49 		ret = mt76_phy_update_channel(phy, conf);
50 	else
51 		ret = 0;
52 	mutex_unlock(&dev->mutex);
53 
54 	return ret;
55 }
56 EXPORT_SYMBOL_GPL(mt76_add_chanctx);
57 
58 void mt76_remove_chanctx(struct ieee80211_hw *hw,
59 			 struct ieee80211_chanctx_conf *conf)
60 {
61 	struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv;
62 	struct mt76_phy *phy = hw->priv;
63 	struct mt76_dev *dev = phy->dev;
64 
65 	phy = ctx->phy;
66 	if (WARN_ON_ONCE(!phy))
67 		return;
68 
69 	if (mt76_phy_scanning(phy))
70 		mt76_abort_scan(dev);
71 
72 	mutex_lock(&dev->mutex);
73 	if (phy->chanctx == ctx)
74 		phy->chanctx = NULL;
75 	mutex_unlock(&dev->mutex);
76 }
77 EXPORT_SYMBOL_GPL(mt76_remove_chanctx);
78 
79 void mt76_change_chanctx(struct ieee80211_hw *hw,
80 			 struct ieee80211_chanctx_conf *conf,
81 			 u32 changed)
82 {
83 	struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv;
84 	struct mt76_phy *phy = ctx->phy;
85 	struct mt76_dev *dev = phy->dev;
86 
87 	if (!(changed & (IEEE80211_CHANCTX_CHANGE_WIDTH |
88 			 IEEE80211_CHANCTX_CHANGE_RADAR)))
89 		return;
90 
91 	if (phy->roc_vif)
92 		mt76_abort_roc(phy);
93 
94 	cancel_delayed_work_sync(&phy->mac_work);
95 
96 	mutex_lock(&dev->mutex);
97 	mt76_phy_update_channel(phy, conf);
98 	mutex_unlock(&dev->mutex);
99 }
100 EXPORT_SYMBOL_GPL(mt76_change_chanctx);
101 
102 
103 int mt76_assign_vif_chanctx(struct ieee80211_hw *hw,
104 			    struct ieee80211_vif *vif,
105 			    struct ieee80211_bss_conf *link_conf,
106 			    struct ieee80211_chanctx_conf *conf)
107 {
108 	struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv;
109 	struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
110 	struct mt76_vif_data *mvif = mlink->mvif;
111 	int link_id = link_conf->link_id;
112 	struct mt76_phy *phy = ctx->phy;
113 	struct mt76_dev *dev = phy->dev;
114 	bool mlink_alloc = false;
115 	int ret = 0;
116 
117 	if (dev->scan.vif == vif && mt76_phy_scanning(phy))
118 		mt76_abort_scan(dev);
119 
120 	mutex_lock(&dev->mutex);
121 
122 	if (vif->type == NL80211_IFTYPE_MONITOR &&
123 	    is_zero_ether_addr(vif->addr))
124 		goto out;
125 
126 	mlink = mt76_vif_conf_link(dev, vif, link_conf);
127 	if (!mlink) {
128 		mlink = mt76_alloc_mlink(dev, mvif);
129 		if (!mlink) {
130 			ret = -ENOMEM;
131 			goto out;
132 		}
133 		mlink_alloc = true;
134 	}
135 
136 	mlink->ctx = conf;
137 	ret = dev->drv->vif_link_add(phy, vif, link_conf, mlink);
138 	if (ret) {
139 		if (mlink_alloc)
140 			kfree(mlink);
141 		goto out;
142 	}
143 
144 	if (link_conf != &vif->bss_conf)
145 		rcu_assign_pointer(mvif->link[link_id], mlink);
146 
147 out:
148 	mutex_unlock(&dev->mutex);
149 
150 	return ret;
151 }
152 EXPORT_SYMBOL_GPL(mt76_assign_vif_chanctx);
153 
154 void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw,
155 			       struct ieee80211_vif *vif,
156 			       struct ieee80211_bss_conf *link_conf,
157 			       struct ieee80211_chanctx_conf *conf)
158 {
159 	struct mt76_chanctx *ctx = (struct mt76_chanctx *)conf->drv_priv;
160 	struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
161 	struct mt76_phy *phy = ctx->phy;
162 	struct mt76_dev *dev = phy->dev;
163 
164 	if (dev->scan.vif == vif && mt76_phy_scanning(phy))
165 		mt76_abort_scan(dev);
166 
167 	mutex_lock(&dev->mutex);
168 
169 	if (vif->type == NL80211_IFTYPE_MONITOR &&
170 	    is_zero_ether_addr(vif->addr))
171 		goto out;
172 
173 	mlink = mt76_vif_conf_link(dev, vif, link_conf);
174 	if (!mlink)
175 		goto out;
176 
177 	dev->drv->vif_link_remove(phy, vif, link_conf, mlink);
178 	mlink->ctx = NULL;
179 out:
180 	mutex_unlock(&dev->mutex);
181 }
182 EXPORT_SYMBOL_GPL(mt76_unassign_vif_chanctx);
183 
184 int mt76_switch_vif_chanctx(struct ieee80211_hw *hw,
185 			    struct ieee80211_vif_chanctx_switch *vifs,
186 			    int n_vifs,
187 			    enum ieee80211_chanctx_switch_mode mode)
188 {
189 	struct ieee80211_vif_chanctx_switch *v;
190 	struct mt76_chanctx *old_ctx, *new_ctx;
191 	struct mt76_phy *old_phy, *phy = hw->priv;
192 	struct mt76_dev *dev = phy->dev;
193 	struct mt76_vif_link *mlink;
194 	bool need_update[__MT_MAX_BAND] = {};
195 	int i, ret = 0;
196 
197 	for (i = 0; i < n_vifs; i++) {
198 		v = &vifs[i];
199 		new_ctx = (struct mt76_chanctx *)v->new_ctx->drv_priv;
200 		if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS)
201 			phy = new_ctx->phy = dev->band_phys[v->new_ctx->def.chan->band];
202 		else
203 			phy = new_ctx->phy;
204 
205 		if (!phy)
206 			return -EINVAL;
207 
208 		if (need_update[phy->band_idx])
209 			continue;
210 
211 		if (phy->chanctx != new_ctx) {
212 			if (mt76_phy_scanning(phy))
213 				mt76_abort_scan(dev);
214 
215 			cancel_delayed_work_sync(&phy->mac_work);
216 			need_update[phy->band_idx] = true;
217 		}
218 	}
219 
220 	mutex_lock(&dev->mutex);
221 
222 	for (i = 0; i < n_vifs; i++) {
223 		v = &vifs[i];
224 		old_ctx = (struct mt76_chanctx *)v->old_ctx->drv_priv;
225 		old_phy = old_ctx->phy;
226 
227 		new_ctx = (struct mt76_chanctx *)v->new_ctx->drv_priv;
228 		phy = new_ctx->phy;
229 
230 		if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS && old_phy->chanctx &&
231 		    old_phy->chanctx == old_ctx && phy != old_phy)
232 			old_phy->chanctx = NULL;
233 
234 		if (need_update[phy->band_idx]) {
235 			ret = mt76_phy_update_channel(phy, v->new_ctx);
236 			if (ret)
237 				goto out;
238 
239 			need_update[phy->band_idx] = false;
240 		}
241 
242 		mlink = mt76_vif_conf_link(dev, v->vif, v->link_conf);
243 		if (!mlink)
244 			continue;
245 
246 		if (old_phy != phy) {
247 			dev->drv->vif_link_remove(old_phy, v->vif, v->link_conf,
248 						  mlink);
249 
250 			ret = dev->drv->vif_link_add(phy, v->vif, v->link_conf,
251 						     mlink);
252 			if (ret)
253 				goto out;
254 		}
255 
256 		mlink->ctx = v->new_ctx;
257 		if (mlink->beacon_mon_interval)
258 			WRITE_ONCE(mlink->beacon_mon_last, jiffies);
259 	}
260 
261 out:
262 	mutex_unlock(&dev->mutex);
263 
264 	return ret;
265 }
266 EXPORT_SYMBOL_GPL(mt76_switch_vif_chanctx);
267 
268 struct mt76_vif_link *mt76_get_vif_phy_link(struct mt76_phy *phy,
269 					    struct ieee80211_vif *vif)
270 {
271 	struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
272 	struct mt76_vif_data *mvif = mlink->mvif;
273 	struct mt76_dev *dev = phy->dev;
274 	int i, ret;
275 
276 	for (i = 0; i < ARRAY_SIZE(mvif->link); i++) {
277 		mlink = mt76_dereference(mvif->link[i], dev);
278 		if (!mlink)
279 			continue;
280 
281 		if (mt76_vif_link_phy(mlink) == phy)
282 			return mlink;
283 	}
284 
285 	if (!dev->drv->vif_link_add)
286 		return ERR_PTR(-EINVAL);
287 
288 	mlink = mt76_alloc_mlink(dev, mvif);
289 	if (!mlink)
290 		return ERR_PTR(-ENOMEM);
291 
292 	mlink->offchannel = true;
293 	ret = dev->drv->vif_link_add(phy, vif, &vif->bss_conf, mlink);
294 	if (ret) {
295 		kfree(mlink);
296 		return ERR_PTR(ret);
297 	}
298 
299 	return mlink;
300 }
301 
302 void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif,
303 			   struct mt76_vif_link *mlink)
304 {
305 	struct mt76_dev *dev = phy->dev;
306 
307 	if (IS_ERR_OR_NULL(mlink) || !mlink->offchannel)
308 		return;
309 
310 	dev->drv->vif_link_remove(phy, vif, &vif->bss_conf, mlink);
311 	kfree_rcu(mlink, rcu_head);
312 }
313 
314 void mt76_roc_complete(struct mt76_phy *phy)
315 {
316 	struct mt76_vif_link *mlink = phy->roc_link;
317 	struct mt76_dev *dev = phy->dev;
318 
319 	if (!phy->roc_vif)
320 		return;
321 
322 	if (mlink)
323 		mlink->mvif->roc_phy = NULL;
324 	if (phy->chanctx && phy->main_chandef.chan && phy->offchannel &&
325 	    !test_bit(MT76_MCU_RESET, &dev->phy.state)) {
326 		__mt76_set_channel(phy, &phy->main_chandef, false);
327 		mt76_offchannel_notify(phy, false);
328 	} else {
329 		phy->offchannel = false;
330 	}
331 	mt76_put_vif_phy_link(phy, phy->roc_vif, phy->roc_link);
332 	phy->roc_vif = NULL;
333 	phy->roc_link = NULL;
334 	if (!test_bit(MT76_RESTART, &dev->phy.state))
335 		ieee80211_remain_on_channel_expired(phy->hw);
336 }
337 
338 void mt76_roc_complete_work(struct work_struct *work)
339 {
340 	struct mt76_phy *phy = container_of(work, struct mt76_phy, roc_work.work);
341 	struct mt76_dev *dev = phy->dev;
342 
343 	mutex_lock(&dev->mutex);
344 	mt76_roc_complete(phy);
345 	mutex_unlock(&dev->mutex);
346 }
347 
348 void mt76_abort_roc(struct mt76_phy *phy)
349 {
350 	struct mt76_dev *dev = phy->dev;
351 
352 	cancel_delayed_work_sync(&phy->roc_work);
353 
354 	mutex_lock(&dev->mutex);
355 	mt76_roc_complete(phy);
356 	mutex_unlock(&dev->mutex);
357 }
358 EXPORT_SYMBOL_GPL(mt76_abort_roc);
359 
360 int mt76_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
361 			   struct ieee80211_channel *chan, int duration,
362 			   enum ieee80211_roc_type type)
363 {
364 	struct cfg80211_chan_def chandef = {};
365 	struct mt76_phy *phy = hw->priv;
366 	struct mt76_dev *dev = phy->dev;
367 	struct mt76_vif_link *mlink;
368 	bool offchannel;
369 	int ret = 0;
370 
371 	phy = dev->band_phys[chan->band];
372 	if (!phy)
373 		return -EINVAL;
374 
375 	cancel_delayed_work_sync(&phy->mac_work);
376 
377 	mutex_lock(&dev->mutex);
378 
379 	if (phy->roc_vif || mt76_phy_scanning(phy) ||
380 	    test_bit(MT76_MCU_RESET, &dev->phy.state) ||
381 	    test_bit(MT76_RESTART, &dev->phy.state)) {
382 		ret = -EBUSY;
383 		goto out;
384 	}
385 
386 	mlink = mt76_get_vif_phy_link(phy, vif);
387 	if (IS_ERR(mlink)) {
388 		ret = PTR_ERR(mlink);
389 		goto out;
390 	}
391 
392 	mlink->mvif->roc_phy = phy;
393 	phy->roc_vif = vif;
394 	phy->roc_link = mlink;
395 
396 	offchannel = mt76_offchannel_chandef(phy, chan, &chandef);
397 	if (offchannel)
398 		mt76_offchannel_notify(phy, true);
399 	ret = __mt76_set_channel(phy, &chandef, offchannel);
400 	if (ret) {
401 		mlink->mvif->roc_phy = NULL;
402 		phy->roc_vif = NULL;
403 		phy->roc_link = NULL;
404 		mt76_put_vif_phy_link(phy, vif, mlink);
405 		goto out;
406 	}
407 	ieee80211_ready_on_channel(hw);
408 	ieee80211_queue_delayed_work(phy->hw, &phy->roc_work,
409 				     msecs_to_jiffies(duration));
410 
411 out:
412 	mutex_unlock(&dev->mutex);
413 	return ret;
414 }
415 EXPORT_SYMBOL_GPL(mt76_remain_on_channel);
416 
417 int mt76_cancel_remain_on_channel(struct ieee80211_hw *hw,
418 				  struct ieee80211_vif *vif)
419 {
420 	struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
421 	struct mt76_vif_data *mvif = mlink->mvif;
422 	struct mt76_phy *phy = mvif->roc_phy;
423 
424 	if (!phy || phy->roc_vif != vif)
425 		return 0;
426 
427 	mt76_abort_roc(phy);
428 
429 	return 0;
430 }
431 EXPORT_SYMBOL_GPL(mt76_cancel_remain_on_channel);
432