1 /*
2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /**
21 * DOC: This file contains RoC API definitions
22 */
23
24 #include <wlan_mgmt_txrx_utils_api.h>
25 #include <wlan_scan_public_structs.h>
26 #include <wlan_scan_api.h>
27 #include <wlan_objmgr_psoc_obj.h>
28 #include <wlan_objmgr_global_obj.h>
29 #include <wlan_objmgr_pdev_obj.h>
30 #include <wlan_objmgr_vdev_obj.h>
31 #include <wlan_policy_mgr_api.h>
32 #include <wlan_utility.h>
33 #include "wlan_p2p_public_struct.h"
34 #include "wlan_p2p_tgt_api.h"
35 #include "wlan_p2p_ucfg_api.h"
36 #include "wlan_p2p_roc.h"
37 #include "wlan_p2p_main.h"
38 #include "wlan_p2p_off_chan_tx.h"
39
40 /**
41 * p2p_mgmt_rx_ops() - register or unregister rx callback
42 * @psoc: psoc object
43 * @isregister: register if true, unregister if false
44 *
45 * This function registers or unregisters rx callback to mgmt txrx
46 * component.
47 *
48 * Return: QDF_STATUS_SUCCESS - in case of success
49 */
p2p_mgmt_rx_ops(struct wlan_objmgr_psoc * psoc,bool isregister)50 static QDF_STATUS p2p_mgmt_rx_ops(struct wlan_objmgr_psoc *psoc,
51 bool isregister)
52 {
53 struct mgmt_txrx_mgmt_frame_cb_info frm_cb_info;
54 QDF_STATUS status;
55
56 p2p_debug("psoc:%pK, is register rx:%d", psoc, isregister);
57
58 frm_cb_info.frm_type = MGMT_PROBE_REQ;
59 frm_cb_info.mgmt_rx_cb = tgt_p2p_mgmt_frame_rx_cb;
60
61 if (isregister)
62 status = wlan_mgmt_txrx_register_rx_cb(psoc,
63 WLAN_UMAC_COMP_P2P, &frm_cb_info, 1);
64 else
65 status = wlan_mgmt_txrx_deregister_rx_cb(psoc,
66 WLAN_UMAC_COMP_P2P, &frm_cb_info, 1);
67
68 return status;
69 }
70
71 /**
72 * p2p_scan_start() - Start scan
73 * @roc_ctx: remain on channel request
74 *
75 * This function trigger a start scan request to scan component.
76 *
77 * Return: QDF_STATUS_SUCCESS - in case of success
78 */
p2p_scan_start(struct p2p_roc_context * roc_ctx)79 static QDF_STATUS p2p_scan_start(struct p2p_roc_context *roc_ctx)
80 {
81 QDF_STATUS status;
82 struct scan_start_request *req;
83 struct wlan_objmgr_vdev *vdev;
84 struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
85 uint32_t go_num;
86 uint8_t ndp_num = 0, nan_disc_enabled_num = 0;
87 struct wlan_objmgr_pdev *pdev;
88 bool is_dbs;
89 enum QDF_OPMODE opmode;
90
91 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
92 p2p_soc_obj->soc, roc_ctx->vdev_id,
93 WLAN_P2P_ID);
94 if (!vdev) {
95 p2p_err("vdev is NULL");
96 return QDF_STATUS_E_INVAL;
97 }
98
99 opmode = wlan_vdev_mlme_get_opmode(vdev);
100
101 req = qdf_mem_malloc(sizeof(*req));
102 if (!req) {
103 status = QDF_STATUS_E_NOMEM;
104 goto fail;
105 }
106
107 wlan_scan_init_default_params(vdev, req);
108
109 if (!roc_ctx->duration) {
110 roc_ctx->duration = P2P_ROC_DEFAULT_DURATION;
111 p2p_debug("use default duration %d",
112 P2P_ROC_DEFAULT_DURATION);
113 }
114
115 pdev = wlan_vdev_get_pdev(vdev);
116 roc_ctx->scan_id = wlan_scan_get_scan_id(p2p_soc_obj->soc);
117 req->vdev = vdev;
118 req->scan_req.scan_id = roc_ctx->scan_id;
119 req->scan_req.scan_type = SCAN_TYPE_P2P_LISTEN;
120 req->scan_req.scan_req_id = p2p_soc_obj->scan_req_id;
121 req->scan_req.chan_list.num_chan = 1;
122 req->scan_req.chan_list.chan[0].freq = roc_ctx->chan_freq;
123 req->scan_req.dwell_time_passive = roc_ctx->duration;
124 req->scan_req.dwell_time_active = 0;
125 req->scan_req.scan_priority = SCAN_PRIORITY_HIGH;
126 req->scan_req.num_bssid = 1;
127 qdf_set_macaddr_broadcast(&req->scan_req.bssid_list[0]);
128
129 if (req->scan_req.dwell_time_passive < P2P_MAX_ROC_DURATION) {
130 go_num = policy_mgr_mode_specific_connection_count(
131 p2p_soc_obj->soc, PM_P2P_GO_MODE, NULL);
132 policy_mgr_mode_specific_num_active_sessions(p2p_soc_obj->soc,
133 QDF_NDI_MODE,
134 &ndp_num);
135 policy_mgr_mode_specific_num_active_sessions(p2p_soc_obj->soc,
136 QDF_NAN_DISC_MODE,
137 &nan_disc_enabled_num);
138 p2p_debug("present go number:%d, NDP number:%d, NAN number:%d",
139 go_num, ndp_num, nan_disc_enabled_num);
140
141 is_dbs = policy_mgr_is_hw_dbs_capable(p2p_soc_obj->soc);
142 /* Modify the ROC duration only for P2P modes */
143 if (opmode == QDF_P2P_DEVICE_MODE ||
144 opmode == QDF_P2P_CLIENT_MODE ||
145 opmode == QDF_P2P_GO_MODE) {
146 if (go_num)
147 /* Check any P2P GO is already present or not. If it's
148 * present then add fixed ROC timer value by 300ms
149 * instead of multiplying with const value which may
150 * lead ROC timer to become 1.5sec. So, in this case fw
151 * will advertize NOA for 1.5 secs and if supplicant
152 * wants to cancel the ROC after 200 or 300ms then fw
153 * can not cancel NOA as ROC is already set to 1.5sec.
154 * And if supplicant sends the next ROC then it might
155 * delay as firmware is already running the presvious
156 * NOA. This may cause the P2P find issue because P2P GO
157 * is already present.
158 * To fix this, add fixed 300ms duration to ROC and
159 * later check if max limit reaches to 600ms then set
160 * max ROC duartion as 600ms only.
161 */
162 req->scan_req.dwell_time_passive +=
163 P2P_ROC_DURATION_MULTI_GO_PRESENT;
164 else
165 req->scan_req.dwell_time_passive *=
166 P2P_ROC_DURATION_MULTI_GO_ABSENT;
167 }
168 /* this is to protect too huge value if some customers
169 * give a higher value from supplicant
170 */
171 if (go_num && req->scan_req.dwell_time_passive >
172 P2P_MAX_ROC_DURATION_GO_PRESENT) {
173 req->scan_req.dwell_time_passive =
174 P2P_MAX_ROC_DURATION_GO_PRESENT;
175 } else if (ndp_num) {
176 if (is_dbs && req->scan_req.dwell_time_passive >
177 P2P_MAX_ROC_DURATION_DBS_NDP_PRESENT)
178 req->scan_req.dwell_time_passive =
179 P2P_MAX_ROC_DURATION_DBS_NDP_PRESENT;
180 else if (!is_dbs && req->scan_req.dwell_time_passive >
181 P2P_MAX_ROC_DURATION_NON_DBS_NDP_PRESENT)
182 req->scan_req.dwell_time_passive =
183 P2P_MAX_ROC_DURATION_NON_DBS_NDP_PRESENT;
184 } else if (nan_disc_enabled_num) {
185 if (is_dbs && req->scan_req.dwell_time_passive >
186 P2P_MAX_ROC_DURATION_DBS_NAN_PRESENT)
187 req->scan_req.dwell_time_passive =
188 P2P_MAX_ROC_DURATION_DBS_NAN_PRESENT;
189 else if (!is_dbs && req->scan_req.dwell_time_passive >
190 P2P_MAX_ROC_DURATION_NON_DBS_NAN_PRESENT)
191 req->scan_req.dwell_time_passive =
192 P2P_MAX_ROC_DURATION_NON_DBS_NAN_PRESENT;
193 } else if (req->scan_req.dwell_time_passive >
194 P2P_MAX_ROC_DURATION) {
195 req->scan_req.dwell_time_passive = P2P_MAX_ROC_DURATION;
196 }
197 }
198 p2p_debug("FW requested roc duration is:%d",
199 req->scan_req.dwell_time_passive);
200
201 status = wlan_scan_start(req);
202
203 p2p_debug("start scan, scan req id:%d, scan id:%d, status:%d",
204 p2p_soc_obj->scan_req_id, roc_ctx->scan_id, status);
205 fail:
206 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
207
208 return status;
209 }
210
211 /**
212 * p2p_roc_abort() - Abort roc
213 * @roc_ctx: remain on channel request
214 *
215 * This function triggers an abort scan request to scan component to abort the
216 * ROC request which is running through roc_ctx.
217 *
218 * Return: QDF_STATUS_SUCCESS - in case of success
219 */
p2p_roc_abort(struct p2p_roc_context * roc_ctx)220 static QDF_STATUS p2p_roc_abort(struct p2p_roc_context *roc_ctx)
221 {
222 QDF_STATUS status;
223 struct scan_cancel_request *req;
224 struct wlan_objmgr_vdev *vdev;
225 struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
226
227 p2p_debug("abort scan, scan req id:%d, scan id:%d",
228 p2p_soc_obj->scan_req_id, roc_ctx->scan_id);
229
230 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
231 p2p_soc_obj->soc, roc_ctx->vdev_id,
232 WLAN_P2P_ID);
233 if (!vdev) {
234 p2p_err("vdev is NULL");
235 return QDF_STATUS_E_INVAL;
236 }
237
238 req = qdf_mem_malloc(sizeof(*req));
239 if (!req) {
240 status = QDF_STATUS_E_NOMEM;
241 goto fail;
242 }
243
244 req->vdev = vdev;
245 req->cancel_req.requester = p2p_soc_obj->scan_req_id;
246 req->cancel_req.scan_id = roc_ctx->scan_id;
247 req->cancel_req.vdev_id = roc_ctx->vdev_id;
248 req->cancel_req.req_type = WLAN_SCAN_CANCEL_SINGLE;
249
250 qdf_mtrace(QDF_MODULE_ID_P2P, QDF_MODULE_ID_SCAN,
251 req->cancel_req.req_type,
252 req->vdev->vdev_objmgr.vdev_id, req->cancel_req.scan_id);
253 status = wlan_scan_cancel(req);
254
255 p2p_debug("abort scan, scan req id:%d, scan id:%d, status:%d",
256 p2p_soc_obj->scan_req_id, roc_ctx->scan_id, status);
257 fail:
258 wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
259
260 return status;
261 }
262
263 /**
264 * p2p_send_roc_event() - Send roc event
265 * @roc_ctx: remain on channel request
266 * @evt: roc event information
267 *
268 * This function send out roc event to up layer.
269 *
270 * Return: QDF_STATUS_SUCCESS - in case of success
271 */
p2p_send_roc_event(struct p2p_roc_context * roc_ctx,enum p2p_roc_event evt)272 static QDF_STATUS p2p_send_roc_event(
273 struct p2p_roc_context *roc_ctx, enum p2p_roc_event evt)
274 {
275 struct p2p_soc_priv_obj *p2p_soc_obj;
276 struct p2p_event p2p_evt;
277 struct p2p_start_param *start_param;
278
279 p2p_soc_obj = roc_ctx->p2p_soc_obj;
280 if (!p2p_soc_obj || !(p2p_soc_obj->start_param)) {
281 p2p_err("Invalid p2p soc object or start parameters");
282 return QDF_STATUS_E_INVAL;
283 }
284 start_param = p2p_soc_obj->start_param;
285 if (!(start_param->event_cb)) {
286 p2p_err("Invalid p2p event callback to up layer");
287 return QDF_STATUS_E_INVAL;
288 }
289
290 p2p_evt.vdev_id = roc_ctx->vdev_id;
291 p2p_evt.roc_event = evt;
292 p2p_evt.cookie = (uint64_t)roc_ctx->id;
293 p2p_evt.chan_freq = roc_ctx->chan_freq;
294 p2p_evt.duration = roc_ctx->duration;
295
296 p2p_debug("roc_event: %d, cookie:%llx", p2p_evt.roc_event,
297 p2p_evt.cookie);
298
299 start_param->event_cb(start_param->event_cb_data, &p2p_evt);
300
301 return QDF_STATUS_SUCCESS;
302 }
303
304 /**
305 * p2p_destroy_roc_ctx() - destroy roc ctx
306 * @roc_ctx: remain on channel request
307 * @up_layer_event: if send uplayer event
308 * @in_roc_queue: if roc context in roc queue
309 *
310 * This function destroy roc context.
311 *
312 * Return: QDF_STATUS_SUCCESS - in case of success
313 */
p2p_destroy_roc_ctx(struct p2p_roc_context * roc_ctx,bool up_layer_event,bool in_roc_queue)314 static QDF_STATUS p2p_destroy_roc_ctx(struct p2p_roc_context *roc_ctx,
315 bool up_layer_event, bool in_roc_queue)
316 {
317 QDF_STATUS status = QDF_STATUS_SUCCESS;
318 struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
319
320 p2p_debug("p2p_soc_obj:%pK, roc_ctx:%pK, up_layer_event:%d,"
321 " in_roc_queue:%d vdev_id:%d freq:%d duration:%d",
322 p2p_soc_obj, roc_ctx, up_layer_event, in_roc_queue,
323 roc_ctx->vdev_id, roc_ctx->chan_freq, roc_ctx->duration);
324
325 if (up_layer_event) {
326 if (roc_ctx->roc_state < ROC_STATE_ON_CHAN)
327 p2p_send_roc_event(roc_ctx, ROC_EVENT_READY_ON_CHAN);
328 p2p_send_roc_event(roc_ctx, ROC_EVENT_COMPLETED);
329 }
330
331 if (in_roc_queue) {
332 status = qdf_list_remove_node(&p2p_soc_obj->roc_q,
333 (qdf_list_node_t *)roc_ctx);
334 if (QDF_STATUS_SUCCESS != status)
335 p2p_err("Failed to remove roc req, status %d", status);
336 }
337
338 qdf_idr_remove(&p2p_soc_obj->p2p_idr, roc_ctx->id);
339 qdf_mem_free(roc_ctx);
340
341 return status;
342 }
343
344 /**
345 * p2p_execute_cancel_roc_req() - Execute cancel roc request
346 * @roc_ctx: remain on channel request
347 *
348 * This function stop roc timer, abort scan and unregister mgmt rx
349 * callback.
350 *
351 * Return: QDF_STATUS_SUCCESS - in case of success
352 */
p2p_execute_cancel_roc_req(struct p2p_roc_context * roc_ctx)353 static QDF_STATUS p2p_execute_cancel_roc_req(
354 struct p2p_roc_context *roc_ctx)
355 {
356 QDF_STATUS status;
357 struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
358
359 p2p_debug("p2p execute cancel roc req");
360
361 roc_ctx->roc_state = ROC_STATE_CANCEL_IN_PROG;
362
363 status = qdf_mc_timer_stop_sync(&roc_ctx->roc_timer);
364 if (status != QDF_STATUS_SUCCESS)
365 p2p_err("Failed to stop roc timer, roc %pK", roc_ctx);
366
367 status = p2p_roc_abort(roc_ctx);
368 if (status != QDF_STATUS_SUCCESS) {
369 p2p_err("Failed to abort scan, status:%d, destroy roc %pK",
370 status, roc_ctx);
371 qdf_mc_timer_destroy(&roc_ctx->roc_timer);
372 p2p_mgmt_rx_ops(p2p_soc_obj->soc, false);
373 p2p_destroy_roc_ctx(roc_ctx, true, true);
374 return status;
375 }
376
377 return QDF_STATUS_SUCCESS;
378 }
379
380 /**
381 * p2p_roc_timeout() - Callback for roc timeout
382 * @pdata: pointer to p2p soc private object
383 *
384 * This function is callback for roc time out.
385 *
386 * Return: None
387 */
p2p_roc_timeout(void * pdata)388 static void p2p_roc_timeout(void *pdata)
389 {
390 struct p2p_roc_context *roc_ctx;
391 struct p2p_soc_priv_obj *p2p_soc_obj;
392
393 p2p_debug("p2p soc obj:%pK", pdata);
394
395 p2p_soc_obj = pdata;
396 if (!p2p_soc_obj) {
397 p2p_err("Invalid p2p soc object");
398 return;
399 }
400
401 roc_ctx = p2p_find_current_roc_ctx(p2p_soc_obj);
402 if (!roc_ctx) {
403 p2p_debug("No P2P roc is pending");
404 return;
405 }
406
407 p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d,"
408 " tx ctx:%pK, freq:%d, phy_mode:%d, duration:%d,"
409 " roc_type:%d, roc_state:%d",
410 roc_ctx->p2p_soc_obj, roc_ctx, roc_ctx->vdev_id,
411 roc_ctx->scan_id, roc_ctx->tx_ctx, roc_ctx->chan_freq,
412 roc_ctx->phy_mode, roc_ctx->duration,
413 roc_ctx->roc_type, roc_ctx->roc_state);
414
415 if (roc_ctx->roc_state == ROC_STATE_CANCEL_IN_PROG) {
416 p2p_err("Cancellation already in progress");
417 return;
418 }
419 p2p_execute_cancel_roc_req(roc_ctx);
420 }
421
422 /**
423 * p2p_execute_roc_req() - Execute roc request
424 * @roc_ctx: remain on channel request
425 *
426 * This function init roc timer, start scan and register mgmt rx
427 * callback.
428 *
429 * Return: QDF_STATUS_SUCCESS - in case of success
430 */
p2p_execute_roc_req(struct p2p_roc_context * roc_ctx)431 static QDF_STATUS p2p_execute_roc_req(struct p2p_roc_context *roc_ctx)
432 {
433 QDF_STATUS status;
434 struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
435
436 p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d,"
437 " tx ctx:%pK, freq:%d, phy_mode:%d, duration:%d,"
438 " roc_type:%d, roc_state:%d",
439 p2p_soc_obj, roc_ctx, roc_ctx->vdev_id,
440 roc_ctx->scan_id, roc_ctx->tx_ctx, roc_ctx->chan_freq,
441 roc_ctx->phy_mode, roc_ctx->duration,
442 roc_ctx->roc_type, roc_ctx->roc_state);
443
444 /* prevent runtime suspend */
445 qdf_runtime_pm_prevent_suspend(&p2p_soc_obj->roc_runtime_lock);
446
447 status = qdf_mc_timer_init(&roc_ctx->roc_timer,
448 QDF_TIMER_TYPE_SW, p2p_roc_timeout,
449 p2p_soc_obj);
450 if (status != QDF_STATUS_SUCCESS) {
451 p2p_err("failed to init roc timer, status:%d", status);
452 goto fail;
453 }
454
455 roc_ctx->roc_state = ROC_STATE_REQUESTED;
456 status = p2p_scan_start(roc_ctx);
457 if (status != QDF_STATUS_SUCCESS) {
458 qdf_mc_timer_destroy(&roc_ctx->roc_timer);
459 p2p_err("Failed to start scan, status:%d", status);
460 goto fail;
461 }
462
463 fail:
464 if (status != QDF_STATUS_SUCCESS) {
465 p2p_destroy_roc_ctx(roc_ctx, true, true);
466 qdf_runtime_pm_allow_suspend(
467 &p2p_soc_obj->roc_runtime_lock);
468 return status;
469 }
470
471 p2p_soc_obj->cur_roc_vdev_id = roc_ctx->vdev_id;
472 status = p2p_mgmt_rx_ops(p2p_soc_obj->soc, true);
473 if (status != QDF_STATUS_SUCCESS)
474 p2p_err("Failed to register mgmt rx callback, status:%d",
475 status);
476
477 return status;
478 }
479
480 /**
481 * p2p_find_roc_ctx() - Find out roc context by cookie
482 * @p2p_soc_obj: p2p psoc private object
483 * @cookie: cookie is the key to find out roc context
484 *
485 * This function find out roc context by cookie from p2p psoc private
486 * object
487 *
488 * Return: Pointer to roc context - success
489 * NULL - failure
490 */
p2p_find_roc_ctx(struct p2p_soc_priv_obj * p2p_soc_obj,uint64_t cookie)491 static struct p2p_roc_context *p2p_find_roc_ctx(
492 struct p2p_soc_priv_obj *p2p_soc_obj, uint64_t cookie)
493 {
494 struct p2p_roc_context *curr_roc_ctx;
495 qdf_list_node_t *p_node;
496 QDF_STATUS status;
497
498 p2p_debug("p2p soc obj:%pK, cookie:%llx", p2p_soc_obj, cookie);
499
500 status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node);
501 while (QDF_IS_STATUS_SUCCESS(status)) {
502 curr_roc_ctx = qdf_container_of(p_node,
503 struct p2p_roc_context, node);
504 if ((uintptr_t) curr_roc_ctx == cookie)
505 return curr_roc_ctx;
506 status = qdf_list_peek_next(&p2p_soc_obj->roc_q,
507 p_node, &p_node);
508 }
509
510 return NULL;
511 }
512
513 /**
514 * p2p_process_scan_start_evt() - Process scan start event
515 * @roc_ctx: remain on channel request
516 *
517 * This function process scan start event.
518 *
519 * Return: QDF_STATUS_SUCCESS - in case of success
520 */
p2p_process_scan_start_evt(struct p2p_roc_context * roc_ctx)521 static QDF_STATUS p2p_process_scan_start_evt(
522 struct p2p_roc_context *roc_ctx)
523 {
524 roc_ctx->roc_state = ROC_STATE_STARTED;
525 p2p_debug("scan started, scan id:%d", roc_ctx->scan_id);
526
527 return QDF_STATUS_SUCCESS;
528 }
529
530 /**
531 * p2p_process_ready_on_channel_evt() - Process ready on channel event
532 * @roc_ctx: remain on channel request
533 *
534 * This function process ready on channel event. Starts roc timer.
535 * Indicates this event to up layer if this is user request roc. Sends
536 * mgmt frame if this is off channel rx roc.
537 *
538 * Return: QDF_STATUS_SUCCESS - in case of success
539 */
p2p_process_ready_on_channel_evt(struct p2p_roc_context * roc_ctx)540 static QDF_STATUS p2p_process_ready_on_channel_evt(
541 struct p2p_roc_context *roc_ctx)
542 {
543 uint64_t cookie;
544 struct p2p_soc_priv_obj *p2p_soc_obj;
545 QDF_STATUS status;
546
547 p2p_soc_obj = roc_ctx->p2p_soc_obj;
548 roc_ctx->roc_state = ROC_STATE_ON_CHAN;
549
550 p2p_debug("scan_id:%d, roc_state:%d", roc_ctx->scan_id,
551 roc_ctx->roc_state);
552
553 status = qdf_mc_timer_start(&roc_ctx->roc_timer,
554 (roc_ctx->duration + P2P_EVENT_PROPAGATE_TIME));
555 if (status != QDF_STATUS_SUCCESS)
556 p2p_err("Remain on Channel timer start failed");
557 if (roc_ctx->roc_type == USER_REQUESTED) {
558 p2p_debug("user required roc, send roc event");
559 status = p2p_send_roc_event(roc_ctx,
560 ROC_EVENT_READY_ON_CHAN);
561 }
562
563 cookie = (uintptr_t)roc_ctx;
564 /* ready to tx frame */
565 p2p_ready_to_tx_frame(p2p_soc_obj, cookie);
566
567 return status;
568 }
569
570 /**
571 * p2p_process_scan_complete_evt() - Process scan complete event
572 * @roc_ctx: remain on channel request
573 *
574 * This function process scan complete event.
575 *
576 * Return: QDF_STATUS_SUCCESS - in case of success
577 */
p2p_process_scan_complete_evt(struct p2p_roc_context * roc_ctx)578 static QDF_STATUS p2p_process_scan_complete_evt(
579 struct p2p_roc_context *roc_ctx)
580 {
581 QDF_STATUS status;
582 qdf_list_node_t *next_node;
583 uint32_t size;
584 struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
585
586 p2p_debug("vdev_id:%d scan_id:%d", roc_ctx->vdev_id, roc_ctx->scan_id);
587
588 /* allow runtime suspend */
589 qdf_runtime_pm_allow_suspend(&p2p_soc_obj->roc_runtime_lock);
590
591
592 status = qdf_mc_timer_stop_sync(&roc_ctx->roc_timer);
593 if (QDF_IS_STATUS_ERROR(status))
594 p2p_err("Failed to stop roc timer");
595
596 status = qdf_mc_timer_destroy(&roc_ctx->roc_timer);
597 if (status != QDF_STATUS_SUCCESS)
598 p2p_err("Failed to destroy roc timer");
599
600 status = p2p_mgmt_rx_ops(p2p_soc_obj->soc, false);
601 p2p_soc_obj->cur_roc_vdev_id = P2P_INVALID_VDEV_ID;
602 if (status != QDF_STATUS_SUCCESS)
603 p2p_err("Failed to deregister mgmt rx callback");
604
605 if (roc_ctx->roc_type == USER_REQUESTED)
606 status = p2p_send_roc_event(roc_ctx,
607 ROC_EVENT_COMPLETED);
608
609 p2p_destroy_roc_ctx(roc_ctx, false, true);
610 qdf_event_set(&p2p_soc_obj->cleanup_roc_done);
611
612 size = qdf_list_size(&p2p_soc_obj->roc_q);
613
614 if (size > 0) {
615 status = qdf_list_peek_front(&p2p_soc_obj->roc_q,
616 &next_node);
617 if (QDF_STATUS_SUCCESS != status) {
618 p2p_err("Failed to peek roc req from front, status %d",
619 status);
620 return status;
621 }
622 roc_ctx = qdf_container_of(next_node,
623 struct p2p_roc_context, node);
624 status = p2p_execute_roc_req(roc_ctx);
625 }
626 return status;
627 }
628
p2p_mgmt_rx_action_ops(struct wlan_objmgr_psoc * psoc,bool isregister)629 QDF_STATUS p2p_mgmt_rx_action_ops(struct wlan_objmgr_psoc *psoc,
630 bool isregister)
631 {
632 struct mgmt_txrx_mgmt_frame_cb_info frm_cb_info[2];
633 QDF_STATUS status;
634
635 p2p_debug("psoc:%pK, is register rx:%d", psoc, isregister);
636
637 frm_cb_info[0].frm_type = MGMT_ACTION_VENDOR_SPECIFIC;
638 frm_cb_info[0].mgmt_rx_cb = tgt_p2p_mgmt_frame_rx_cb;
639 frm_cb_info[1].frm_type = MGMT_ACTION_CATEGORY_VENDOR_SPECIFIC;
640 frm_cb_info[1].mgmt_rx_cb = tgt_p2p_mgmt_frame_rx_cb;
641
642 if (isregister)
643 status = wlan_mgmt_txrx_register_rx_cb(psoc,
644 WLAN_UMAC_COMP_P2P, frm_cb_info, 2);
645 else
646 status = wlan_mgmt_txrx_deregister_rx_cb(psoc,
647 WLAN_UMAC_COMP_P2P, frm_cb_info, 2);
648
649 return status;
650 }
651
p2p_find_current_roc_ctx(struct p2p_soc_priv_obj * p2p_soc_obj)652 struct p2p_roc_context *p2p_find_current_roc_ctx(
653 struct p2p_soc_priv_obj *p2p_soc_obj)
654 {
655 struct p2p_roc_context *roc_ctx;
656 qdf_list_node_t *p_node;
657 QDF_STATUS status;
658
659 status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node);
660 while (QDF_IS_STATUS_SUCCESS(status)) {
661 roc_ctx = qdf_container_of(p_node,
662 struct p2p_roc_context, node);
663 if (roc_ctx->roc_state != ROC_STATE_IDLE) {
664 p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id"
665 ":%d, scan_id:%d, tx ctx:%pK, freq:"
666 "%d, phy_mode:%d, duration:%d, "
667 "roc_type:%d, roc_state:%d",
668 roc_ctx->p2p_soc_obj, roc_ctx,
669 roc_ctx->vdev_id, roc_ctx->scan_id,
670 roc_ctx->tx_ctx, roc_ctx->chan_freq,
671 roc_ctx->phy_mode, roc_ctx->duration,
672 roc_ctx->roc_type, roc_ctx->roc_state);
673
674 return roc_ctx;
675 }
676 status = qdf_list_peek_next(&p2p_soc_obj->roc_q,
677 p_node, &p_node);
678 }
679
680 return NULL;
681 }
682
p2p_find_roc_by_tx_ctx(struct p2p_soc_priv_obj * p2p_soc_obj,uint64_t cookie)683 struct p2p_roc_context *p2p_find_roc_by_tx_ctx(
684 struct p2p_soc_priv_obj *p2p_soc_obj, uint64_t cookie)
685 {
686 struct p2p_roc_context *curr_roc_ctx;
687 qdf_list_node_t *p_node;
688 QDF_STATUS status;
689
690 p2p_debug("p2p soc obj:%pK, cookie:%llx", p2p_soc_obj, cookie);
691
692 status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node);
693 while (QDF_IS_STATUS_SUCCESS(status)) {
694 curr_roc_ctx = qdf_container_of(p_node,
695 struct p2p_roc_context, node);
696 if ((uintptr_t) curr_roc_ctx->tx_ctx == cookie)
697 return curr_roc_ctx;
698 status = qdf_list_peek_next(&p2p_soc_obj->roc_q,
699 p_node, &p_node);
700 }
701
702 return NULL;
703 }
704
p2p_find_roc_by_chan_freq(struct p2p_soc_priv_obj * p2p_soc_obj,qdf_freq_t chan_freq)705 struct p2p_roc_context *p2p_find_roc_by_chan_freq(
706 struct p2p_soc_priv_obj *p2p_soc_obj, qdf_freq_t chan_freq)
707 {
708 struct p2p_roc_context *roc_ctx;
709 qdf_list_node_t *p_node;
710 QDF_STATUS status;
711
712 status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node);
713 while (QDF_IS_STATUS_SUCCESS(status)) {
714 roc_ctx = qdf_container_of(p_node,
715 struct p2p_roc_context,
716 node);
717 if (roc_ctx->chan_freq == chan_freq) {
718 p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d,"
719 " scan_id:%d, tx ctx:%pK, freq:%d,"
720 " phy_mode:%d, duration:%d,"
721 " roc_type:%d, roc_state:%d",
722 roc_ctx->p2p_soc_obj, roc_ctx,
723 roc_ctx->vdev_id, roc_ctx->scan_id,
724 roc_ctx->tx_ctx, roc_ctx->chan_freq,
725 roc_ctx->phy_mode, roc_ctx->duration,
726 roc_ctx->roc_type, roc_ctx->roc_state);
727
728 return roc_ctx;
729 }
730 status = qdf_list_peek_next(&p2p_soc_obj->roc_q,
731 p_node, &p_node);
732 }
733
734 return NULL;
735 }
736
p2p_restart_roc_timer(struct p2p_roc_context * roc_ctx)737 QDF_STATUS p2p_restart_roc_timer(struct p2p_roc_context *roc_ctx)
738 {
739 QDF_STATUS status = QDF_STATUS_E_FAILURE;
740
741 if (QDF_TIMER_STATE_RUNNING ==
742 qdf_mc_timer_get_current_state(&roc_ctx->roc_timer)) {
743 p2p_debug("roc restart duration:%d", roc_ctx->duration);
744 status = qdf_mc_timer_stop_sync(&roc_ctx->roc_timer);
745 if (status != QDF_STATUS_SUCCESS) {
746 p2p_err("Failed to stop roc timer");
747 return status;
748 }
749
750 status = qdf_mc_timer_start(&roc_ctx->roc_timer,
751 roc_ctx->duration);
752 if (status != QDF_STATUS_SUCCESS)
753 p2p_err("Remain on Channel timer start failed");
754 }
755
756 return status;
757 }
758
p2p_cleanup_roc(struct p2p_soc_priv_obj * p2p_soc_obj,struct wlan_objmgr_vdev * vdev,bool sync)759 QDF_STATUS p2p_cleanup_roc(struct p2p_soc_priv_obj *p2p_soc_obj,
760 struct wlan_objmgr_vdev *vdev,
761 bool sync)
762 {
763 struct scheduler_msg msg = {0};
764 struct p2p_cleanup_param *param;
765 QDF_STATUS status;
766 uint32_t vdev_id;
767
768 if (!p2p_soc_obj) {
769 p2p_err("p2p soc context is NULL");
770 return QDF_STATUS_E_FAILURE;
771 }
772
773 p2p_debug("p2p_soc_obj:%pK, vdev:%pK, sync:%d", p2p_soc_obj, vdev,
774 sync);
775 param = qdf_mem_malloc(sizeof(*param));
776 if (!param)
777 return QDF_STATUS_E_NOMEM;
778
779 param->p2p_soc_obj = p2p_soc_obj;
780 if (vdev)
781 vdev_id = (uint32_t)wlan_vdev_get_id(vdev);
782 else
783 vdev_id = P2P_INVALID_VDEV_ID;
784 param->vdev_id = vdev_id;
785 qdf_event_reset(&p2p_soc_obj->cleanup_roc_done);
786 msg.type = P2P_CLEANUP_ROC;
787 msg.bodyptr = param;
788 msg.callback = p2p_process_cmd;
789 status = scheduler_post_message(QDF_MODULE_ID_P2P,
790 QDF_MODULE_ID_P2P,
791 QDF_MODULE_ID_OS_IF, &msg);
792 if (status != QDF_STATUS_SUCCESS) {
793 qdf_mem_free(param);
794 return status;
795 }
796
797 if (!sync)
798 return status;
799
800 status = qdf_wait_single_event(
801 &p2p_soc_obj->cleanup_roc_done,
802 P2P_WAIT_CLEANUP_ROC);
803
804 if (status != QDF_STATUS_SUCCESS)
805 p2p_err("wait for cleanup roc timeout, %d", status);
806
807 return status;
808 }
809
p2p_process_cleanup_roc_queue(struct p2p_cleanup_param * param)810 QDF_STATUS p2p_process_cleanup_roc_queue(
811 struct p2p_cleanup_param *param)
812 {
813 uint32_t vdev_id;
814 uint8_t count = 0;
815 QDF_STATUS status, ret;
816 struct p2p_roc_context *roc_ctx;
817 qdf_list_node_t *p_node;
818 struct p2p_soc_priv_obj *p2p_soc_obj;
819
820 if (!param || !(param->p2p_soc_obj)) {
821 p2p_err("Invalid cleanup param");
822 return QDF_STATUS_E_FAILURE;
823 }
824
825 p2p_soc_obj = param->p2p_soc_obj;
826 vdev_id = param->vdev_id;
827
828 p2p_debug("clean up idle roc request, roc queue size:%d, vdev id:%d",
829 qdf_list_size(&p2p_soc_obj->roc_q), vdev_id);
830 status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node);
831 while (QDF_IS_STATUS_SUCCESS(status)) {
832 roc_ctx = qdf_container_of(p_node,
833 struct p2p_roc_context, node);
834
835 p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, "
836 "scan_id:%d, tx ctx:%pK, freq:%d, phy_mode:%d, "
837 "duration:%d, roc_type:%d, roc_state:%d",
838 roc_ctx->p2p_soc_obj, roc_ctx,
839 roc_ctx->vdev_id, roc_ctx->scan_id,
840 roc_ctx->tx_ctx, roc_ctx->chan_freq,
841 roc_ctx->phy_mode, roc_ctx->duration,
842 roc_ctx->roc_type, roc_ctx->roc_state);
843 status = qdf_list_peek_next(&p2p_soc_obj->roc_q,
844 p_node, &p_node);
845 if ((roc_ctx->roc_state == ROC_STATE_IDLE) &&
846 ((vdev_id == P2P_INVALID_VDEV_ID) ||
847 (vdev_id == roc_ctx->vdev_id))) {
848 ret = qdf_list_remove_node(
849 &p2p_soc_obj->roc_q,
850 (qdf_list_node_t *)roc_ctx);
851 if (ret == QDF_STATUS_SUCCESS)
852 qdf_mem_free(roc_ctx);
853 else
854 p2p_err("Failed to remove roc ctx from queue");
855 }
856 }
857
858 p2p_debug("clean up started roc request, roc queue size:%d",
859 qdf_list_size(&p2p_soc_obj->roc_q));
860 status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node);
861 while (QDF_IS_STATUS_SUCCESS(status)) {
862 roc_ctx = qdf_container_of(p_node,
863 struct p2p_roc_context, node);
864
865 p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, "
866 "scan_id:%d, tx ctx:%pK, freq:%d, phy_mode:%d, "
867 "duration:%d, roc_type:%d, roc_state:%d",
868 roc_ctx->p2p_soc_obj, roc_ctx, roc_ctx->vdev_id,
869 roc_ctx->scan_id, roc_ctx->tx_ctx, roc_ctx->chan_freq,
870 roc_ctx->phy_mode, roc_ctx->duration,
871 roc_ctx->roc_type, roc_ctx->roc_state);
872
873 status = qdf_list_peek_next(&p2p_soc_obj->roc_q,
874 p_node, &p_node);
875 if ((roc_ctx->roc_state != ROC_STATE_IDLE) &&
876 ((vdev_id == P2P_INVALID_VDEV_ID) ||
877 (vdev_id == roc_ctx->vdev_id))) {
878 if (roc_ctx->roc_state !=
879 ROC_STATE_CANCEL_IN_PROG)
880 p2p_execute_cancel_roc_req(roc_ctx);
881
882 count++;
883 }
884 }
885
886 p2p_debug("count %d", count);
887 if (!count)
888 qdf_event_set(&p2p_soc_obj->cleanup_roc_done);
889
890 return QDF_STATUS_SUCCESS;
891 }
892
p2p_process_roc_req(struct p2p_roc_context * roc_ctx)893 QDF_STATUS p2p_process_roc_req(struct p2p_roc_context *roc_ctx)
894 {
895 struct p2p_soc_priv_obj *p2p_soc_obj;
896 struct p2p_roc_context *curr_roc_ctx;
897 QDF_STATUS status;
898 uint32_t size;
899
900 p2p_soc_obj = roc_ctx->p2p_soc_obj;
901
902 p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d, "
903 "tx_ctx:%pK, freq:%d, phy_mode:%d, duration:%d, "
904 "roc_type:%d, roc_state:%d",
905 p2p_soc_obj, roc_ctx, roc_ctx->vdev_id,
906 roc_ctx->scan_id, roc_ctx->tx_ctx, roc_ctx->chan_freq,
907 roc_ctx->phy_mode, roc_ctx->duration,
908 roc_ctx->roc_type, roc_ctx->roc_state);
909
910 status = qdf_list_insert_back(&p2p_soc_obj->roc_q,
911 &roc_ctx->node);
912 if (QDF_STATUS_SUCCESS != status) {
913 p2p_destroy_roc_ctx(roc_ctx, true, false);
914 p2p_debug("Failed to insert roc req, status %d", status);
915 return status;
916 }
917
918 size = qdf_list_size(&p2p_soc_obj->roc_q);
919 if (size == 1) {
920 status = p2p_execute_roc_req(roc_ctx);
921 } else if (size > 1) {
922 curr_roc_ctx = p2p_find_current_roc_ctx(p2p_soc_obj);
923 /*TODO, to handle extend roc */
924 }
925
926 return status;
927 }
928
p2p_process_cancel_roc_req(struct cancel_roc_context * cancel_roc_ctx)929 QDF_STATUS p2p_process_cancel_roc_req(
930 struct cancel_roc_context *cancel_roc_ctx)
931 {
932 struct p2p_soc_priv_obj *p2p_soc_obj;
933 struct p2p_roc_context *curr_roc_ctx;
934 QDF_STATUS status;
935
936 p2p_soc_obj = cancel_roc_ctx->p2p_soc_obj;
937 curr_roc_ctx = p2p_find_roc_ctx(p2p_soc_obj,
938 cancel_roc_ctx->cookie);
939
940 if (!curr_roc_ctx) {
941 p2p_debug("Failed to find roc req by cookie, cookie %llx",
942 cancel_roc_ctx->cookie);
943 return QDF_STATUS_E_INVAL;
944 }
945
946 p2p_debug("roc ctx:%pK vdev_id:%d, scan_id:%d, roc_type:%d, roc_state:%d",
947 curr_roc_ctx, curr_roc_ctx->vdev_id, curr_roc_ctx->scan_id,
948 curr_roc_ctx->roc_type, curr_roc_ctx->roc_state);
949
950 if (curr_roc_ctx->roc_state == ROC_STATE_IDLE) {
951 status = p2p_destroy_roc_ctx(curr_roc_ctx, true, true);
952 } else if (curr_roc_ctx->roc_state ==
953 ROC_STATE_CANCEL_IN_PROG) {
954 p2p_debug("Receive cancel roc req when roc req is canceling, cookie %llx",
955 cancel_roc_ctx->cookie);
956 status = QDF_STATUS_SUCCESS;
957 } else {
958 status = p2p_execute_cancel_roc_req(curr_roc_ctx);
959 }
960
961 return status;
962 }
963
p2p_scan_event_cb(struct wlan_objmgr_vdev * vdev,struct scan_event * event,void * arg)964 void p2p_scan_event_cb(struct wlan_objmgr_vdev *vdev,
965 struct scan_event *event, void *arg)
966 {
967 struct p2p_soc_priv_obj *p2p_soc_obj;
968 struct p2p_roc_context *curr_roc_ctx;
969
970 p2p_debug("soc:%pK, scan event:%d", arg, event->type);
971
972 p2p_soc_obj = (struct p2p_soc_priv_obj *)arg;
973 if (!p2p_soc_obj) {
974 p2p_err("Invalid P2P context");
975 return;
976 }
977
978 curr_roc_ctx = p2p_find_current_roc_ctx(p2p_soc_obj);
979 if (!curr_roc_ctx) {
980 p2p_err("Failed to find valid P2P roc context");
981 return;
982 }
983
984 qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_P2P, event->type,
985 event->vdev_id, event->scan_id);
986 switch (event->type) {
987 case SCAN_EVENT_TYPE_STARTED:
988 p2p_process_scan_start_evt(curr_roc_ctx);
989 break;
990 case SCAN_EVENT_TYPE_FOREIGN_CHANNEL:
991 p2p_process_ready_on_channel_evt(curr_roc_ctx);
992 break;
993 case SCAN_EVENT_TYPE_COMPLETED:
994 case SCAN_EVENT_TYPE_DEQUEUED:
995 case SCAN_EVENT_TYPE_START_FAILED:
996 p2p_process_scan_complete_evt(curr_roc_ctx);
997 break;
998 default:
999 p2p_debug("drop scan event, %d", event->type);
1000 }
1001 }
1002