xref: /wlan-driver/qcacld-3.0/components/p2p/core/src/wlan_p2p_roc.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
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