Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * Off-channel operation helpers
4 : : *
5 : : * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
6 : : * Copyright 2004, Instant802 Networks, Inc.
7 : : * Copyright 2005, Devicescape Software, Inc.
8 : : * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
9 : : * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
10 : : * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
11 : : * Copyright (C) 2019 Intel Corporation
12 : : */
13 : : #include <linux/export.h>
14 : : #include <net/mac80211.h>
15 : : #include "ieee80211_i.h"
16 : : #include "driver-ops.h"
17 : :
18 : : /*
19 : : * Tell our hardware to disable PS.
20 : : * Optionally inform AP that we will go to sleep so that it will buffer
21 : : * the frames while we are doing off-channel work. This is optional
22 : : * because we *may* be doing work on-operating channel, and want our
23 : : * hardware unconditionally awake, but still let the AP send us normal frames.
24 : : */
25 : 0 : static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
26 : : {
27 : 0 : struct ieee80211_local *local = sdata->local;
28 : 0 : struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
29 : :
30 : 0 : local->offchannel_ps_enabled = false;
31 : :
32 : : /* FIXME: what to do when local->pspolling is true? */
33 : :
34 : 0 : del_timer_sync(&local->dynamic_ps_timer);
35 : 0 : del_timer_sync(&ifmgd->bcn_mon_timer);
36 : 0 : del_timer_sync(&ifmgd->conn_mon_timer);
37 : :
38 : 0 : cancel_work_sync(&local->dynamic_ps_enable_work);
39 : :
40 [ # # ]: 0 : if (local->hw.conf.flags & IEEE80211_CONF_PS) {
41 : 0 : local->offchannel_ps_enabled = true;
42 : 0 : local->hw.conf.flags &= ~IEEE80211_CONF_PS;
43 : 0 : ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
44 : : }
45 : :
46 [ # # # # ]: 0 : if (!local->offchannel_ps_enabled ||
47 : : !ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK))
48 : : /*
49 : : * If power save was enabled, no need to send a nullfunc
50 : : * frame because AP knows that we are sleeping. But if the
51 : : * hardware is creating the nullfunc frame for power save
52 : : * status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not
53 : : * enabled) and power save was enabled, the firmware just
54 : : * sent a null frame with power save disabled. So we need
55 : : * to send a new nullfunc frame to inform the AP that we
56 : : * are again sleeping.
57 : : */
58 : 0 : ieee80211_send_nullfunc(local, sdata, true);
59 : 0 : }
60 : :
61 : : /* inform AP that we are awake again, unless power save is enabled */
62 : 0 : static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata)
63 : : {
64 : 0 : struct ieee80211_local *local = sdata->local;
65 : :
66 [ # # ]: 0 : if (!local->ps_sdata)
67 : 0 : ieee80211_send_nullfunc(local, sdata, false);
68 [ # # ]: 0 : else if (local->offchannel_ps_enabled) {
69 : : /*
70 : : * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware
71 : : * will send a nullfunc frame with the powersave bit set
72 : : * even though the AP already knows that we are sleeping.
73 : : * This could be avoided by sending a null frame with power
74 : : * save bit disabled before enabling the power save, but
75 : : * this doesn't gain anything.
76 : : *
77 : : * When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need
78 : : * to send a nullfunc frame because AP already knows that
79 : : * we are sleeping, let's just enable power save mode in
80 : : * hardware.
81 : : */
82 : : /* TODO: Only set hardware if CONF_PS changed?
83 : : * TODO: Should we set offchannel_ps_enabled to false?
84 : : */
85 : 0 : local->hw.conf.flags |= IEEE80211_CONF_PS;
86 : 0 : ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
87 [ # # ]: 0 : } else if (local->hw.conf.dynamic_ps_timeout > 0) {
88 : : /*
89 : : * If IEEE80211_CONF_PS was not set and the dynamic_ps_timer
90 : : * had been running before leaving the operating channel,
91 : : * restart the timer now and send a nullfunc frame to inform
92 : : * the AP that we are awake.
93 : : */
94 : 0 : ieee80211_send_nullfunc(local, sdata, false);
95 : 0 : mod_timer(&local->dynamic_ps_timer, jiffies +
96 [ # # ]: 0 : msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
97 : : }
98 : :
99 : 0 : ieee80211_sta_reset_beacon_monitor(sdata);
100 : 0 : ieee80211_sta_reset_conn_monitor(sdata);
101 : 0 : }
102 : :
103 : 0 : void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
104 : : {
105 : 0 : struct ieee80211_sub_if_data *sdata;
106 : :
107 [ # # # # ]: 0 : if (WARN_ON(local->use_chanctx))
108 : : return;
109 : :
110 : : /*
111 : : * notify the AP about us leaving the channel and stop all
112 : : * STA interfaces.
113 : : */
114 : :
115 : : /*
116 : : * Stop queues and transmit all frames queued by the driver
117 : : * before sending nullfunc to enable powersave at the AP.
118 : : */
119 : 0 : ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
120 : : IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
121 : : false);
122 : 0 : ieee80211_flush_queues(local, NULL, false);
123 : :
124 : 0 : mutex_lock(&local->iflist_mtx);
125 [ # # ]: 0 : list_for_each_entry(sdata, &local->interfaces, list) {
126 [ # # ]: 0 : if (!ieee80211_sdata_running(sdata))
127 : 0 : continue;
128 : :
129 [ # # ]: 0 : if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
130 : : sdata->vif.type == NL80211_IFTYPE_NAN)
131 : 0 : continue;
132 : :
133 [ # # ]: 0 : if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
134 : 0 : set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
135 : :
136 : : /* Check to see if we should disable beaconing. */
137 [ # # ]: 0 : if (sdata->vif.bss_conf.enable_beacon) {
138 : 0 : set_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED,
139 : : &sdata->state);
140 : 0 : sdata->vif.bss_conf.enable_beacon = false;
141 : 0 : ieee80211_bss_info_change_notify(
142 : : sdata, BSS_CHANGED_BEACON_ENABLED);
143 : : }
144 : :
145 [ # # ]: 0 : if (sdata->vif.type == NL80211_IFTYPE_STATION &&
146 [ # # ]: 0 : sdata->u.mgd.associated)
147 : 0 : ieee80211_offchannel_ps_enable(sdata);
148 : : }
149 : 0 : mutex_unlock(&local->iflist_mtx);
150 : : }
151 : :
152 : 0 : void ieee80211_offchannel_return(struct ieee80211_local *local)
153 : : {
154 : 0 : struct ieee80211_sub_if_data *sdata;
155 : :
156 [ # # # # ]: 0 : if (WARN_ON(local->use_chanctx))
157 : : return;
158 : :
159 : 0 : mutex_lock(&local->iflist_mtx);
160 [ # # ]: 0 : list_for_each_entry(sdata, &local->interfaces, list) {
161 [ # # ]: 0 : if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE)
162 : 0 : continue;
163 : :
164 [ # # ]: 0 : if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
165 : 0 : clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
166 : :
167 [ # # ]: 0 : if (!ieee80211_sdata_running(sdata))
168 : 0 : continue;
169 : :
170 : : /* Tell AP we're back */
171 [ # # ]: 0 : if (sdata->vif.type == NL80211_IFTYPE_STATION &&
172 [ # # ]: 0 : sdata->u.mgd.associated)
173 : 0 : ieee80211_offchannel_ps_disable(sdata);
174 : :
175 [ # # ]: 0 : if (test_and_clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED,
176 : : &sdata->state)) {
177 : 0 : sdata->vif.bss_conf.enable_beacon = true;
178 : 0 : ieee80211_bss_info_change_notify(
179 : : sdata, BSS_CHANGED_BEACON_ENABLED);
180 : : }
181 : : }
182 : 0 : mutex_unlock(&local->iflist_mtx);
183 : :
184 : 0 : ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP,
185 : : IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
186 : : false);
187 : : }
188 : :
189 : 0 : static void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
190 : : {
191 : : /* was never transmitted */
192 [ # # ]: 0 : if (roc->frame) {
193 : 0 : cfg80211_mgmt_tx_status(&roc->sdata->wdev, roc->mgmt_tx_cookie,
194 : 0 : roc->frame->data, roc->frame->len,
195 : : false, GFP_KERNEL);
196 : 0 : ieee80211_free_txskb(&roc->sdata->local->hw, roc->frame);
197 : : }
198 : :
199 [ # # ]: 0 : if (!roc->mgmt_tx_cookie)
200 : 0 : cfg80211_remain_on_channel_expired(&roc->sdata->wdev,
201 : : roc->cookie, roc->chan,
202 : : GFP_KERNEL);
203 : : else
204 : 0 : cfg80211_tx_mgmt_expired(&roc->sdata->wdev,
205 : : roc->mgmt_tx_cookie,
206 : : roc->chan, GFP_KERNEL);
207 : :
208 : 0 : list_del(&roc->list);
209 : 0 : kfree(roc);
210 : 0 : }
211 : :
212 : 0 : static unsigned long ieee80211_end_finished_rocs(struct ieee80211_local *local,
213 : : unsigned long now)
214 : : {
215 : 0 : struct ieee80211_roc_work *roc, *tmp;
216 : 0 : long remaining_dur_min = LONG_MAX;
217 : :
218 : 0 : lockdep_assert_held(&local->mtx);
219 : :
220 [ # # ]: 0 : list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
221 : 0 : long remaining;
222 : :
223 [ # # ]: 0 : if (!roc->started)
224 : : break;
225 : :
226 : 0 : remaining = roc->start_time +
227 [ # # ]: 0 : msecs_to_jiffies(roc->duration) -
228 : : now;
229 : :
230 : : /* In case of HW ROC, it is possible that the HW finished the
231 : : * ROC session before the actual requested time. In such a case
232 : : * end the ROC session (disregarding the remaining time).
233 : : */
234 [ # # # # ]: 0 : if (roc->abort || roc->hw_begun || remaining <= 0)
235 : 0 : ieee80211_roc_notify_destroy(roc);
236 : : else
237 : 0 : remaining_dur_min = min(remaining_dur_min, remaining);
238 : : }
239 : :
240 : 0 : return remaining_dur_min;
241 : : }
242 : :
243 : 0 : static bool ieee80211_recalc_sw_work(struct ieee80211_local *local,
244 : : unsigned long now)
245 : : {
246 : 0 : long dur = ieee80211_end_finished_rocs(local, now);
247 : :
248 [ # # ]: 0 : if (dur == LONG_MAX)
249 : : return false;
250 : :
251 : 0 : mod_delayed_work(local->workqueue, &local->roc_work, dur);
252 : 0 : return true;
253 : : }
254 : :
255 : 0 : static void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc,
256 : : unsigned long start_time)
257 : : {
258 [ # # # # ]: 0 : if (WARN_ON(roc->notified))
259 : : return;
260 : :
261 : 0 : roc->start_time = start_time;
262 : 0 : roc->started = true;
263 : :
264 [ # # ]: 0 : if (roc->mgmt_tx_cookie) {
265 [ # # # # ]: 0 : if (!WARN_ON(!roc->frame)) {
266 : 0 : ieee80211_tx_skb_tid_band(roc->sdata, roc->frame, 7,
267 : 0 : roc->chan->band, 0);
268 : 0 : roc->frame = NULL;
269 : : }
270 : : } else {
271 : 0 : cfg80211_ready_on_channel(&roc->sdata->wdev, roc->cookie,
272 : : roc->chan, roc->req_duration,
273 : : GFP_KERNEL);
274 : : }
275 : :
276 : 0 : roc->notified = true;
277 : : }
278 : :
279 : 0 : static void ieee80211_hw_roc_start(struct work_struct *work)
280 : : {
281 : 0 : struct ieee80211_local *local =
282 : 0 : container_of(work, struct ieee80211_local, hw_roc_start);
283 : 0 : struct ieee80211_roc_work *roc;
284 : :
285 : 0 : mutex_lock(&local->mtx);
286 : :
287 [ # # ]: 0 : list_for_each_entry(roc, &local->roc_list, list) {
288 [ # # ]: 0 : if (!roc->started)
289 : : break;
290 : :
291 : 0 : roc->hw_begun = true;
292 : 0 : ieee80211_handle_roc_started(roc, local->hw_roc_start_time);
293 : : }
294 : :
295 : 0 : mutex_unlock(&local->mtx);
296 : 0 : }
297 : :
298 : 0 : void ieee80211_ready_on_channel(struct ieee80211_hw *hw)
299 : : {
300 : 0 : struct ieee80211_local *local = hw_to_local(hw);
301 : :
302 : 0 : local->hw_roc_start_time = jiffies;
303 : :
304 : 0 : trace_api_ready_on_channel(local);
305 : :
306 : 0 : ieee80211_queue_work(hw, &local->hw_roc_start);
307 : 0 : }
308 : : EXPORT_SYMBOL_GPL(ieee80211_ready_on_channel);
309 : :
310 : 0 : static void _ieee80211_start_next_roc(struct ieee80211_local *local)
311 : : {
312 : 0 : struct ieee80211_roc_work *roc, *tmp;
313 : 0 : enum ieee80211_roc_type type;
314 : 0 : u32 min_dur, max_dur;
315 : :
316 : 0 : lockdep_assert_held(&local->mtx);
317 : :
318 [ # # # # ]: 0 : if (WARN_ON(list_empty(&local->roc_list)))
319 : : return;
320 : :
321 : 0 : roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work,
322 : : list);
323 : :
324 [ # # # # ]: 0 : if (WARN_ON(roc->started))
325 : : return;
326 : :
327 : 0 : min_dur = roc->duration;
328 : 0 : max_dur = roc->duration;
329 : 0 : type = roc->type;
330 : :
331 [ # # ]: 0 : list_for_each_entry(tmp, &local->roc_list, list) {
332 [ # # ]: 0 : if (tmp == roc)
333 : 0 : continue;
334 [ # # # # ]: 0 : if (tmp->sdata != roc->sdata || tmp->chan != roc->chan)
335 : : break;
336 : 0 : max_dur = max(tmp->duration, max_dur);
337 : 0 : min_dur = min(tmp->duration, min_dur);
338 : 0 : type = max(tmp->type, type);
339 : : }
340 : :
341 [ # # ]: 0 : if (local->ops->remain_on_channel) {
342 : 0 : int ret = drv_remain_on_channel(local, roc->sdata, roc->chan,
343 : : max_dur, type);
344 : :
345 [ # # ]: 0 : if (ret) {
346 : 0 : wiphy_warn(local->hw.wiphy,
347 : : "failed to start next HW ROC (%d)\n", ret);
348 : : /*
349 : : * queue the work struct again to avoid recursion
350 : : * when multiple failures occur
351 : : */
352 [ # # ]: 0 : list_for_each_entry(tmp, &local->roc_list, list) {
353 [ # # ]: 0 : if (tmp->sdata != roc->sdata ||
354 [ # # ]: 0 : tmp->chan != roc->chan)
355 : : break;
356 : 0 : tmp->started = true;
357 : 0 : tmp->abort = true;
358 : : }
359 : 0 : ieee80211_queue_work(&local->hw, &local->hw_roc_done);
360 : 0 : return;
361 : : }
362 : :
363 : : /* we'll notify about the start once the HW calls back */
364 [ # # ]: 0 : list_for_each_entry(tmp, &local->roc_list, list) {
365 [ # # # # ]: 0 : if (tmp->sdata != roc->sdata || tmp->chan != roc->chan)
366 : : break;
367 : 0 : tmp->started = true;
368 : : }
369 : : } else {
370 : : /* If actually operating on the desired channel (with at least
371 : : * 20 MHz channel width) don't stop all the operations but still
372 : : * treat it as though the ROC operation started properly, so
373 : : * other ROC operations won't interfere with this one.
374 : : */
375 : 0 : roc->on_channel = roc->chan == local->_oper_chandef.chan &&
376 [ # # # # : 0 : local->_oper_chandef.width != NL80211_CHAN_WIDTH_5 &&
# # ]
377 : : local->_oper_chandef.width != NL80211_CHAN_WIDTH_10;
378 : :
379 : : /* start this ROC */
380 : 0 : ieee80211_recalc_idle(local);
381 : :
382 [ # # ]: 0 : if (!roc->on_channel) {
383 : 0 : ieee80211_offchannel_stop_vifs(local);
384 : :
385 : 0 : local->tmp_channel = roc->chan;
386 : 0 : ieee80211_hw_config(local, 0);
387 : : }
388 : :
389 [ # # ]: 0 : ieee80211_queue_delayed_work(&local->hw, &local->roc_work,
390 : : msecs_to_jiffies(min_dur));
391 : :
392 : : /* tell userspace or send frame(s) */
393 [ # # ]: 0 : list_for_each_entry(tmp, &local->roc_list, list) {
394 [ # # # # ]: 0 : if (tmp->sdata != roc->sdata || tmp->chan != roc->chan)
395 : : break;
396 : :
397 : 0 : tmp->on_channel = roc->on_channel;
398 : 0 : ieee80211_handle_roc_started(tmp, jiffies);
399 : : }
400 : : }
401 : : }
402 : :
403 : 0 : void ieee80211_start_next_roc(struct ieee80211_local *local)
404 : : {
405 : 0 : struct ieee80211_roc_work *roc;
406 : :
407 : 0 : lockdep_assert_held(&local->mtx);
408 : :
409 [ # # ]: 0 : if (list_empty(&local->roc_list)) {
410 : 0 : ieee80211_run_deferred_scan(local);
411 : 0 : return;
412 : : }
413 : :
414 : : /* defer roc if driver is not started (i.e. during reconfig) */
415 [ # # ]: 0 : if (local->in_reconfig)
416 : : return;
417 : :
418 : 0 : roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work,
419 : : list);
420 : :
421 [ # # # # ]: 0 : if (WARN_ON_ONCE(roc->started))
422 : : return;
423 : :
424 [ # # ]: 0 : if (local->ops->remain_on_channel) {
425 : 0 : _ieee80211_start_next_roc(local);
426 : : } else {
427 : : /* delay it a bit */
428 : 0 : ieee80211_queue_delayed_work(&local->hw, &local->roc_work,
429 : : round_jiffies_relative(HZ/2));
430 : : }
431 : : }
432 : :
433 : 0 : static void __ieee80211_roc_work(struct ieee80211_local *local)
434 : : {
435 : 0 : struct ieee80211_roc_work *roc;
436 : 0 : bool on_channel;
437 : :
438 : 0 : lockdep_assert_held(&local->mtx);
439 : :
440 [ # # # # ]: 0 : if (WARN_ON(local->ops->remain_on_channel))
441 : : return;
442 : :
443 [ # # ]: 0 : roc = list_first_entry_or_null(&local->roc_list,
444 : : struct ieee80211_roc_work, list);
445 [ # # ]: 0 : if (!roc)
446 : : return;
447 : :
448 [ # # ]: 0 : if (!roc->started) {
449 [ # # ]: 0 : WARN_ON(local->use_chanctx);
450 : 0 : _ieee80211_start_next_roc(local);
451 : : } else {
452 : 0 : on_channel = roc->on_channel;
453 [ # # ]: 0 : if (ieee80211_recalc_sw_work(local, jiffies))
454 : : return;
455 : :
456 : : /* careful - roc pointer became invalid during recalc */
457 : :
458 [ # # ]: 0 : if (!on_channel) {
459 : 0 : ieee80211_flush_queues(local, NULL, false);
460 : :
461 : 0 : local->tmp_channel = NULL;
462 : 0 : ieee80211_hw_config(local, 0);
463 : :
464 : 0 : ieee80211_offchannel_return(local);
465 : : }
466 : :
467 : 0 : ieee80211_recalc_idle(local);
468 : 0 : ieee80211_start_next_roc(local);
469 : : }
470 : : }
471 : :
472 : 0 : static void ieee80211_roc_work(struct work_struct *work)
473 : : {
474 : 0 : struct ieee80211_local *local =
475 : 0 : container_of(work, struct ieee80211_local, roc_work.work);
476 : :
477 : 0 : mutex_lock(&local->mtx);
478 : 0 : __ieee80211_roc_work(local);
479 : 0 : mutex_unlock(&local->mtx);
480 : 0 : }
481 : :
482 : 0 : static void ieee80211_hw_roc_done(struct work_struct *work)
483 : : {
484 : 0 : struct ieee80211_local *local =
485 : 0 : container_of(work, struct ieee80211_local, hw_roc_done);
486 : :
487 : 0 : mutex_lock(&local->mtx);
488 : :
489 : 0 : ieee80211_end_finished_rocs(local, jiffies);
490 : :
491 : : /* if there's another roc, start it now */
492 : 0 : ieee80211_start_next_roc(local);
493 : :
494 : 0 : mutex_unlock(&local->mtx);
495 : 0 : }
496 : :
497 : 0 : void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw)
498 : : {
499 : 0 : struct ieee80211_local *local = hw_to_local(hw);
500 : :
501 : 0 : trace_api_remain_on_channel_expired(local);
502 : :
503 : 0 : ieee80211_queue_work(hw, &local->hw_roc_done);
504 : 0 : }
505 : : EXPORT_SYMBOL_GPL(ieee80211_remain_on_channel_expired);
506 : :
507 : : static bool
508 : : ieee80211_coalesce_hw_started_roc(struct ieee80211_local *local,
509 : : struct ieee80211_roc_work *new_roc,
510 : : struct ieee80211_roc_work *cur_roc)
511 : : {
512 : : unsigned long now = jiffies;
513 : : unsigned long remaining;
514 : :
515 : : if (WARN_ON(!cur_roc->started))
516 : : return false;
517 : :
518 : : /* if it was scheduled in the hardware, but not started yet,
519 : : * we can only combine if the older one had a longer duration
520 : : */
521 : : if (!cur_roc->hw_begun && new_roc->duration > cur_roc->duration)
522 : : return false;
523 : :
524 : : remaining = cur_roc->start_time +
525 : : msecs_to_jiffies(cur_roc->duration) -
526 : : now;
527 : :
528 : : /* if it doesn't fit entirely, schedule a new one */
529 : : if (new_roc->duration > jiffies_to_msecs(remaining))
530 : : return false;
531 : :
532 : : /* add just after the current one so we combine their finish later */
533 : : list_add(&new_roc->list, &cur_roc->list);
534 : :
535 : : /* if the existing one has already begun then let this one also
536 : : * begin, otherwise they'll both be marked properly by the work
537 : : * struct that runs once the driver notifies us of the beginning
538 : : */
539 : : if (cur_roc->hw_begun) {
540 : : new_roc->hw_begun = true;
541 : : ieee80211_handle_roc_started(new_roc, now);
542 : : }
543 : :
544 : : return true;
545 : : }
546 : :
547 : 0 : static int ieee80211_start_roc_work(struct ieee80211_local *local,
548 : : struct ieee80211_sub_if_data *sdata,
549 : : struct ieee80211_channel *channel,
550 : : unsigned int duration, u64 *cookie,
551 : : struct sk_buff *txskb,
552 : : enum ieee80211_roc_type type)
553 : : {
554 : 0 : struct ieee80211_roc_work *roc, *tmp;
555 : 0 : bool queued = false, combine_started = true;
556 : 0 : int ret;
557 : :
558 : 0 : lockdep_assert_held(&local->mtx);
559 : :
560 [ # # # # ]: 0 : if (local->use_chanctx && !local->ops->remain_on_channel)
561 : : return -EOPNOTSUPP;
562 : :
563 : 0 : roc = kzalloc(sizeof(*roc), GFP_KERNEL);
564 [ # # ]: 0 : if (!roc)
565 : : return -ENOMEM;
566 : :
567 : : /*
568 : : * If the duration is zero, then the driver
569 : : * wouldn't actually do anything. Set it to
570 : : * 10 for now.
571 : : *
572 : : * TODO: cancel the off-channel operation
573 : : * when we get the SKB's TX status and
574 : : * the wait time was zero before.
575 : : */
576 [ # # ]: 0 : if (!duration)
577 : 0 : duration = 10;
578 : :
579 : 0 : roc->chan = channel;
580 : 0 : roc->duration = duration;
581 : 0 : roc->req_duration = duration;
582 : 0 : roc->frame = txskb;
583 : 0 : roc->type = type;
584 : 0 : roc->sdata = sdata;
585 : :
586 : : /*
587 : : * cookie is either the roc cookie (for normal roc)
588 : : * or the SKB (for mgmt TX)
589 : : */
590 [ # # ]: 0 : if (!txskb) {
591 : 0 : roc->cookie = ieee80211_mgmt_tx_cookie(local);
592 : 0 : *cookie = roc->cookie;
593 : : } else {
594 : 0 : roc->mgmt_tx_cookie = *cookie;
595 : : }
596 : :
597 : : /* if there's no need to queue, handle it immediately */
598 [ # # ]: 0 : if (list_empty(&local->roc_list) &&
599 [ # # # # ]: 0 : !local->scanning && !ieee80211_is_radar_required(local)) {
600 : : /* if not HW assist, just queue & schedule work */
601 [ # # ]: 0 : if (!local->ops->remain_on_channel) {
602 : 0 : list_add_tail(&roc->list, &local->roc_list);
603 : 0 : ieee80211_queue_delayed_work(&local->hw,
604 : : &local->roc_work, 0);
605 : : } else {
606 : : /* otherwise actually kick it off here
607 : : * (for error handling)
608 : : */
609 : 0 : ret = drv_remain_on_channel(local, sdata, channel,
610 : : duration, type);
611 [ # # ]: 0 : if (ret) {
612 : 0 : kfree(roc);
613 : 0 : return ret;
614 : : }
615 : 0 : roc->started = true;
616 : 0 : list_add_tail(&roc->list, &local->roc_list);
617 : : }
618 : :
619 : 0 : return 0;
620 : : }
621 : :
622 : : /* otherwise handle queueing */
623 : :
624 [ # # ]: 0 : list_for_each_entry(tmp, &local->roc_list, list) {
625 [ # # # # ]: 0 : if (tmp->chan != channel || tmp->sdata != sdata)
626 : 0 : continue;
627 : :
628 : : /*
629 : : * Extend this ROC if possible: If it hasn't started, add
630 : : * just after the new one to combine.
631 : : */
632 [ # # ]: 0 : if (!tmp->started) {
633 : 0 : list_add(&roc->list, &tmp->list);
634 : 0 : queued = true;
635 : 0 : break;
636 : : }
637 : :
638 [ # # ]: 0 : if (!combine_started)
639 : 0 : continue;
640 : :
641 [ # # ]: 0 : if (!local->ops->remain_on_channel) {
642 : : /* If there's no hardware remain-on-channel, and
643 : : * doing so won't push us over the maximum r-o-c
644 : : * we allow, then we can just add the new one to
645 : : * the list and mark it as having started now.
646 : : * If it would push over the limit, don't try to
647 : : * combine with other started ones (that haven't
648 : : * been running as long) but potentially sort it
649 : : * with others that had the same fate.
650 : : */
651 : 0 : unsigned long now = jiffies;
652 : 0 : u32 elapsed = jiffies_to_msecs(now - tmp->start_time);
653 : 0 : struct wiphy *wiphy = local->hw.wiphy;
654 : 0 : u32 max_roc = wiphy->max_remain_on_channel_duration;
655 : :
656 [ # # ]: 0 : if (elapsed + roc->duration > max_roc) {
657 : 0 : combine_started = false;
658 : 0 : continue;
659 : : }
660 : :
661 : 0 : list_add(&roc->list, &tmp->list);
662 : 0 : queued = true;
663 : 0 : roc->on_channel = tmp->on_channel;
664 : 0 : ieee80211_handle_roc_started(roc, now);
665 : 0 : ieee80211_recalc_sw_work(local, now);
666 : 0 : break;
667 : : }
668 : :
669 : 0 : queued = ieee80211_coalesce_hw_started_roc(local, roc, tmp);
670 [ # # ]: 0 : if (queued)
671 : : break;
672 : : /* if it wasn't queued, perhaps it can be combined with
673 : : * another that also couldn't get combined previously,
674 : : * but no need to check for already started ones, since
675 : : * that can't work.
676 : : */
677 : : combine_started = false;
678 : : }
679 : :
680 [ # # ]: 0 : if (!queued)
681 : 0 : list_add_tail(&roc->list, &local->roc_list);
682 : :
683 : : return 0;
684 : : }
685 : :
686 : 0 : int ieee80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
687 : : struct ieee80211_channel *chan,
688 : : unsigned int duration, u64 *cookie)
689 : : {
690 : 0 : struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
691 : 0 : struct ieee80211_local *local = sdata->local;
692 : 0 : int ret;
693 : :
694 : 0 : mutex_lock(&local->mtx);
695 : 0 : ret = ieee80211_start_roc_work(local, sdata, chan,
696 : : duration, cookie, NULL,
697 : : IEEE80211_ROC_TYPE_NORMAL);
698 : 0 : mutex_unlock(&local->mtx);
699 : :
700 : 0 : return ret;
701 : : }
702 : :
703 : 0 : static int ieee80211_cancel_roc(struct ieee80211_local *local,
704 : : u64 cookie, bool mgmt_tx)
705 : : {
706 : 0 : struct ieee80211_roc_work *roc, *tmp, *found = NULL;
707 : 0 : int ret;
708 : :
709 [ # # ]: 0 : if (!cookie)
710 : : return -ENOENT;
711 : :
712 : 0 : flush_work(&local->hw_roc_start);
713 : :
714 : 0 : mutex_lock(&local->mtx);
715 [ # # ]: 0 : list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
716 [ # # # # ]: 0 : if (!mgmt_tx && roc->cookie != cookie)
717 : 0 : continue;
718 [ # # # # ]: 0 : else if (mgmt_tx && roc->mgmt_tx_cookie != cookie)
719 : 0 : continue;
720 : :
721 : : found = roc;
722 : : break;
723 : : }
724 : :
725 [ # # ]: 0 : if (!found) {
726 : 0 : mutex_unlock(&local->mtx);
727 : 0 : return -ENOENT;
728 : : }
729 : :
730 [ # # ]: 0 : if (!found->started) {
731 : 0 : ieee80211_roc_notify_destroy(found);
732 : 0 : goto out_unlock;
733 : : }
734 : :
735 [ # # ]: 0 : if (local->ops->remain_on_channel) {
736 : 0 : ret = drv_cancel_remain_on_channel(local, roc->sdata);
737 [ # # # # ]: 0 : if (WARN_ON_ONCE(ret)) {
738 : 0 : mutex_unlock(&local->mtx);
739 : 0 : return ret;
740 : : }
741 : :
742 : : /* TODO:
743 : : * if multiple items were combined here then we really shouldn't
744 : : * cancel them all - we should wait for as much time as needed
745 : : * for the longest remaining one, and only then cancel ...
746 : : */
747 [ # # ]: 0 : list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
748 [ # # ]: 0 : if (!roc->started)
749 : : break;
750 [ # # ]: 0 : if (roc == found)
751 : 0 : found = NULL;
752 : 0 : ieee80211_roc_notify_destroy(roc);
753 : : }
754 : :
755 : : /* that really must not happen - it was started */
756 [ # # ]: 0 : WARN_ON(found);
757 : :
758 : 0 : ieee80211_start_next_roc(local);
759 : : } else {
760 : : /* go through work struct to return to the operating channel */
761 : 0 : found->abort = true;
762 : 0 : mod_delayed_work(local->workqueue, &local->roc_work, 0);
763 : : }
764 : :
765 : 0 : out_unlock:
766 : 0 : mutex_unlock(&local->mtx);
767 : :
768 : 0 : return 0;
769 : : }
770 : :
771 : 0 : int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
772 : : struct wireless_dev *wdev, u64 cookie)
773 : : {
774 : 0 : struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
775 : 0 : struct ieee80211_local *local = sdata->local;
776 : :
777 : 0 : return ieee80211_cancel_roc(local, cookie, false);
778 : : }
779 : :
780 : 0 : int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
781 : : struct cfg80211_mgmt_tx_params *params, u64 *cookie)
782 : : {
783 [ # # ]: 0 : struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
784 : 0 : struct ieee80211_local *local = sdata->local;
785 : 0 : struct sk_buff *skb;
786 : 0 : struct sta_info *sta;
787 : 0 : const struct ieee80211_mgmt *mgmt = (void *)params->buf;
788 : 0 : bool need_offchan = false;
789 : 0 : u32 flags;
790 : 0 : int ret;
791 : 0 : u8 *data;
792 : :
793 [ # # ]: 0 : if (params->dont_wait_for_ack)
794 : : flags = IEEE80211_TX_CTL_NO_ACK;
795 : : else
796 : 0 : flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
797 : : IEEE80211_TX_CTL_REQ_TX_STATUS;
798 : :
799 [ # # ]: 0 : if (params->no_cck)
800 : 0 : flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
801 : :
802 [ # # # # : 0 : switch (sdata->vif.type) {
# ]
803 : 0 : case NL80211_IFTYPE_ADHOC:
804 [ # # ]: 0 : if (!sdata->vif.bss_conf.ibss_joined)
805 : 0 : need_offchan = true;
806 : : #ifdef CONFIG_MAC80211_MESH
807 : : /* fall through */
808 : : case NL80211_IFTYPE_MESH_POINT:
809 : : if (ieee80211_vif_is_mesh(&sdata->vif) &&
810 : : !sdata->u.mesh.mesh_id_len)
811 : : need_offchan = true;
812 : : #endif
813 : : /* fall through */
814 : : case NL80211_IFTYPE_AP:
815 : : case NL80211_IFTYPE_AP_VLAN:
816 : : case NL80211_IFTYPE_P2P_GO:
817 [ # # ]: 0 : if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
818 [ # # ]: 0 : !ieee80211_vif_is_mesh(&sdata->vif) &&
819 [ # # ]: 0 : !rcu_access_pointer(sdata->bss->beacon))
820 : 0 : need_offchan = true;
821 [ # # ]: 0 : if (!ieee80211_is_action(mgmt->frame_control) ||
822 [ # # # # ]: 0 : mgmt->u.action.category == WLAN_CATEGORY_PUBLIC ||
823 [ # # ]: 0 : mgmt->u.action.category == WLAN_CATEGORY_SELF_PROTECTED ||
824 : : mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT)
825 : : break;
826 : 0 : rcu_read_lock();
827 : 0 : sta = sta_info_get_bss(sdata, mgmt->da);
828 : 0 : rcu_read_unlock();
829 [ # # ]: 0 : if (!sta)
830 : : return -ENOLINK;
831 : : break;
832 : : case NL80211_IFTYPE_STATION:
833 : : case NL80211_IFTYPE_P2P_CLIENT:
834 : 0 : sdata_lock(sdata);
835 [ # # ]: 0 : if (!sdata->u.mgd.associated ||
836 [ # # # # ]: 0 : (params->offchan && params->wait &&
837 [ # # ]: 0 : local->ops->remain_on_channel &&
838 : 0 : memcmp(sdata->u.mgd.associated->bssid,
839 [ # # ]: 0 : mgmt->bssid, ETH_ALEN)))
840 : 0 : need_offchan = true;
841 : 0 : sdata_unlock(sdata);
842 : : break;
843 : : case NL80211_IFTYPE_P2P_DEVICE:
844 : : need_offchan = true;
845 : : break;
846 : : case NL80211_IFTYPE_NAN:
847 : : default:
848 : : return -EOPNOTSUPP;
849 : : }
850 : :
851 : : /* configurations requiring offchan cannot work if no channel has been
852 : : * specified
853 : : */
854 [ # # # # ]: 0 : if (need_offchan && !params->chan)
855 : : return -EINVAL;
856 : :
857 : 0 : mutex_lock(&local->mtx);
858 : :
859 : : /* Check if the operating channel is the requested channel */
860 [ # # ]: 0 : if (!need_offchan) {
861 : 0 : struct ieee80211_chanctx_conf *chanctx_conf;
862 : :
863 : 0 : rcu_read_lock();
864 [ # # ]: 0 : chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
865 : :
866 [ # # ]: 0 : if (chanctx_conf) {
867 [ # # ]: 0 : need_offchan = params->chan &&
868 : : (params->chan !=
869 [ # # ]: 0 : chanctx_conf->def.chan);
870 [ # # ]: 0 : } else if (!params->chan) {
871 : 0 : ret = -EINVAL;
872 : 0 : rcu_read_unlock();
873 : 0 : goto out_unlock;
874 : : } else {
875 : : need_offchan = true;
876 : : }
877 : 0 : rcu_read_unlock();
878 : : }
879 : :
880 [ # # # # ]: 0 : if (need_offchan && !params->offchan) {
881 : 0 : ret = -EBUSY;
882 : 0 : goto out_unlock;
883 : : }
884 : :
885 : 0 : skb = dev_alloc_skb(local->hw.extra_tx_headroom + params->len);
886 [ # # ]: 0 : if (!skb) {
887 : 0 : ret = -ENOMEM;
888 : 0 : goto out_unlock;
889 : : }
890 : 0 : skb_reserve(skb, local->hw.extra_tx_headroom);
891 : :
892 : 0 : data = skb_put_data(skb, params->buf, params->len);
893 : :
894 : : /* Update CSA counters */
895 [ # # ]: 0 : if (sdata->vif.csa_active &&
896 [ # # ]: 0 : (sdata->vif.type == NL80211_IFTYPE_AP ||
897 [ # # ]: 0 : sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
898 : 0 : sdata->vif.type == NL80211_IFTYPE_ADHOC) &&
899 [ # # ]: 0 : params->n_csa_offsets) {
900 : 0 : int i;
901 : 0 : struct beacon_data *beacon = NULL;
902 : :
903 : 0 : rcu_read_lock();
904 : :
905 [ # # ]: 0 : if (sdata->vif.type == NL80211_IFTYPE_AP)
906 : 0 : beacon = rcu_dereference(sdata->u.ap.beacon);
907 [ # # ]: 0 : else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
908 : 0 : beacon = rcu_dereference(sdata->u.ibss.presp);
909 : : else if (ieee80211_vif_is_mesh(&sdata->vif))
910 : : beacon = rcu_dereference(sdata->u.mesh.beacon);
911 : :
912 [ # # ]: 0 : if (beacon)
913 [ # # ]: 0 : for (i = 0; i < params->n_csa_offsets; i++)
914 : 0 : data[params->csa_offsets[i]] =
915 : 0 : beacon->csa_current_counter;
916 : :
917 : 0 : rcu_read_unlock();
918 : : }
919 : :
920 [ # # ]: 0 : IEEE80211_SKB_CB(skb)->flags = flags;
921 : :
922 : 0 : skb->dev = sdata->dev;
923 : :
924 [ # # ]: 0 : if (!params->dont_wait_for_ack) {
925 : : /* make a copy to preserve the frame contents
926 : : * in case of encryption.
927 : : */
928 : 0 : ret = ieee80211_attach_ack_skb(local, skb, cookie, GFP_KERNEL);
929 [ # # ]: 0 : if (ret) {
930 : 0 : kfree_skb(skb);
931 : 0 : goto out_unlock;
932 : : }
933 : : } else {
934 : : /* Assign a dummy non-zero cookie, it's not sent to
935 : : * userspace in this case but we rely on its value
936 : : * internally in the need_offchan case to distinguish
937 : : * mgmt-tx from remain-on-channel.
938 : : */
939 : 0 : *cookie = 0xffffffff;
940 : : }
941 : :
942 [ # # ]: 0 : if (!need_offchan) {
943 : 0 : ieee80211_tx_skb(sdata, skb);
944 : 0 : ret = 0;
945 : 0 : goto out_unlock;
946 : : }
947 : :
948 : 0 : IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN |
949 : : IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
950 [ # # ]: 0 : if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL))
951 : 0 : IEEE80211_SKB_CB(skb)->hw_queue =
952 : 0 : local->hw.offchannel_tx_hw_queue;
953 : :
954 : : /* This will handle all kinds of coalescing and immediate TX */
955 : 0 : ret = ieee80211_start_roc_work(local, sdata, params->chan,
956 : : params->wait, cookie, skb,
957 : : IEEE80211_ROC_TYPE_MGMT_TX);
958 [ # # ]: 0 : if (ret)
959 : 0 : ieee80211_free_txskb(&local->hw, skb);
960 : 0 : out_unlock:
961 : 0 : mutex_unlock(&local->mtx);
962 : 0 : return ret;
963 : : }
964 : :
965 : 0 : int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
966 : : struct wireless_dev *wdev, u64 cookie)
967 : : {
968 [ # # ]: 0 : struct ieee80211_local *local = wiphy_priv(wiphy);
969 : :
970 : 0 : return ieee80211_cancel_roc(local, cookie, true);
971 : : }
972 : :
973 : 30 : void ieee80211_roc_setup(struct ieee80211_local *local)
974 : : {
975 : 30 : INIT_WORK(&local->hw_roc_start, ieee80211_hw_roc_start);
976 : 30 : INIT_WORK(&local->hw_roc_done, ieee80211_hw_roc_done);
977 : 30 : INIT_DELAYED_WORK(&local->roc_work, ieee80211_roc_work);
978 : 30 : INIT_LIST_HEAD(&local->roc_list);
979 : 30 : }
980 : :
981 : 0 : void ieee80211_roc_purge(struct ieee80211_local *local,
982 : : struct ieee80211_sub_if_data *sdata)
983 : : {
984 : 0 : struct ieee80211_roc_work *roc, *tmp;
985 : 0 : bool work_to_do = false;
986 : :
987 : 0 : mutex_lock(&local->mtx);
988 [ # # ]: 0 : list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
989 [ # # # # ]: 0 : if (sdata && roc->sdata != sdata)
990 : 0 : continue;
991 : :
992 [ # # ]: 0 : if (roc->started) {
993 [ # # ]: 0 : if (local->ops->remain_on_channel) {
994 : : /* can race, so ignore return value */
995 : 0 : drv_cancel_remain_on_channel(local, sdata);
996 : 0 : ieee80211_roc_notify_destroy(roc);
997 : : } else {
998 : 0 : roc->abort = true;
999 : 0 : work_to_do = true;
1000 : : }
1001 : : } else {
1002 : 0 : ieee80211_roc_notify_destroy(roc);
1003 : : }
1004 : : }
1005 [ # # ]: 0 : if (work_to_do)
1006 : 0 : __ieee80211_roc_work(local);
1007 : 0 : mutex_unlock(&local->mtx);
1008 : 0 : }
|