xref: /wlan-driver/qcacld-3.0/components/p2p/core/src/wlan_p2p_main.c (revision 5113495b16420b49004c444715d2daae2066e7dc) !
1 /*
2  * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 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 main P2P function definitions
22  */
23 
24 #include <scheduler_api.h>
25 #include <wlan_objmgr_psoc_obj.h>
26 #include <wlan_objmgr_global_obj.h>
27 #include <wlan_objmgr_pdev_obj.h>
28 #include <wlan_objmgr_vdev_obj.h>
29 #include <wlan_objmgr_peer_obj.h>
30 #include <wlan_scan_api.h>
31 #include "wlan_p2p_public_struct.h"
32 #include "wlan_p2p_ucfg_api.h"
33 #include "wlan_p2p_tgt_api.h"
34 #include "wlan_p2p_mcc_quota_tgt_api.h"
35 #include "wlan_p2p_main.h"
36 #include "wlan_p2p_roc.h"
37 #include "wlan_p2p_off_chan_tx.h"
38 #include "cfg_p2p.h"
39 #include "cfg_ucfg_api.h"
40 #include "wlan_mlme_api.h"
41 
42 /**
43  * p2p_get_cmd_type_str() - parse cmd to string
44  * @cmd_type: P2P cmd type
45  *
46  * This function parse P2P cmd to string.
47  *
48  * Return: command string
49  */
p2p_get_cmd_type_str(enum p2p_cmd_type cmd_type)50 static char *p2p_get_cmd_type_str(enum p2p_cmd_type cmd_type)
51 {
52 	switch (cmd_type) {
53 	case P2P_ROC_REQ:
54 		return "P2P roc request";
55 	case P2P_CANCEL_ROC_REQ:
56 		return "P2P cancel roc request";
57 	case P2P_MGMT_TX:
58 		return "P2P mgmt tx request";
59 	case P2P_MGMT_TX_CANCEL:
60 		return "P2P cancel mgmt tx request";
61 	case P2P_CLEANUP_ROC:
62 		return "P2P cleanup roc";
63 	case P2P_CLEANUP_TX:
64 		return "P2P cleanup tx";
65 	case P2P_SET_RANDOM_MAC:
66 		return "P2P set random mac";
67 	default:
68 		return "Invalid P2P command";
69 	}
70 }
71 
72 /**
73  * p2p_get_event_type_str() - parase event to string
74  * @event_type: P2P event type
75  *
76  * This function parse P2P event to string.
77  *
78  * Return: event string
79  */
p2p_get_event_type_str(enum p2p_event_type event_type)80 static char *p2p_get_event_type_str(enum p2p_event_type event_type)
81 {
82 	switch (event_type) {
83 	case P2P_EVENT_SCAN_EVENT:
84 		return "P2P scan event";
85 	case P2P_EVENT_MGMT_TX_ACK_CNF:
86 		return "P2P mgmt tx ack event";
87 	case P2P_EVENT_RX_MGMT:
88 		return "P2P mgmt rx event";
89 	case P2P_EVENT_LO_STOPPED:
90 		return "P2P lo stop event";
91 	case P2P_EVENT_NOA:
92 		return "P2P noa event";
93 	case P2P_EVENT_ADD_MAC_RSP:
94 		return "P2P add mac filter resp event";
95 	default:
96 		return "Invalid P2P event";
97 	}
98 }
99 
100 /**
101  * p2p_psoc_obj_create_notification() - Function to allocate per P2P
102  * soc private object
103  * @soc: soc context
104  * @data: Pointer to data
105  *
106  * This function gets called from object manager when psoc is being
107  * created and creates p2p soc context.
108  *
109  * Return: QDF_STATUS_SUCCESS - in case of success
110  */
p2p_psoc_obj_create_notification(struct wlan_objmgr_psoc * soc,void * data)111 static QDF_STATUS p2p_psoc_obj_create_notification(
112 	struct wlan_objmgr_psoc *soc, void *data)
113 {
114 	struct p2p_soc_priv_obj *p2p_soc_obj;
115 	QDF_STATUS status;
116 
117 	if (!soc) {
118 		p2p_err("psoc context passed is NULL");
119 		return QDF_STATUS_E_INVAL;
120 	}
121 
122 	p2p_soc_obj = qdf_mem_malloc(sizeof(*p2p_soc_obj));
123 	if (!p2p_soc_obj)
124 		return QDF_STATUS_E_NOMEM;
125 
126 	p2p_soc_obj->soc = soc;
127 
128 	status = wlan_objmgr_psoc_component_obj_attach(soc,
129 				WLAN_UMAC_COMP_P2P, p2p_soc_obj,
130 				QDF_STATUS_SUCCESS);
131 	if (status != QDF_STATUS_SUCCESS) {
132 		qdf_mem_free(p2p_soc_obj);
133 		p2p_err("Failed to attach p2p component, %d", status);
134 		return status;
135 	}
136 
137 	p2p_debug("p2p soc object create successful, %pK", p2p_soc_obj);
138 
139 	return QDF_STATUS_SUCCESS;
140 }
141 
142 /**
143  * p2p_psoc_obj_destroy_notification() - Free soc private object
144  * @soc: soc context
145  * @data: Pointer to data
146  *
147  * This function gets called from object manager when psoc is being
148  * deleted and delete p2p soc context.
149  *
150  * Return: QDF_STATUS_SUCCESS - in case of success
151  */
p2p_psoc_obj_destroy_notification(struct wlan_objmgr_psoc * soc,void * data)152 static QDF_STATUS p2p_psoc_obj_destroy_notification(
153 	struct wlan_objmgr_psoc *soc, void *data)
154 {
155 	struct p2p_soc_priv_obj *p2p_soc_obj;
156 	QDF_STATUS status;
157 
158 	if (!soc) {
159 		p2p_err("psoc context passed is NULL");
160 		return QDF_STATUS_E_INVAL;
161 	}
162 
163 	p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc,
164 			WLAN_UMAC_COMP_P2P);
165 	if (!p2p_soc_obj) {
166 		p2p_err("p2p soc private object is NULL");
167 		return QDF_STATUS_E_FAILURE;
168 	}
169 
170 	p2p_soc_obj->soc = NULL;
171 
172 	status = wlan_objmgr_psoc_component_obj_detach(soc,
173 				WLAN_UMAC_COMP_P2P, p2p_soc_obj);
174 	if (status != QDF_STATUS_SUCCESS) {
175 		p2p_err("Failed to detach p2p component, %d", status);
176 		return status;
177 	}
178 
179 	p2p_debug("destroy p2p soc object, %pK", p2p_soc_obj);
180 
181 	qdf_mem_free(p2p_soc_obj);
182 
183 	return QDF_STATUS_SUCCESS;
184 }
185 
186 /**
187  * p2p_vdev_obj_create_notification() - Allocate per p2p vdev object
188  * @vdev: vdev context
189  * @data: Pointer to data
190  *
191  * This function gets called from object manager when vdev is being
192  * created and creates p2p vdev context.
193  *
194  * Return: QDF_STATUS_SUCCESS - in case of success
195  */
p2p_vdev_obj_create_notification(struct wlan_objmgr_vdev * vdev,void * data)196 static QDF_STATUS p2p_vdev_obj_create_notification(
197 	struct wlan_objmgr_vdev *vdev, void *data)
198 {
199 	struct p2p_vdev_priv_obj *p2p_vdev_obj;
200 	QDF_STATUS status;
201 	enum QDF_OPMODE mode;
202 
203 	if (!vdev) {
204 		p2p_err("vdev context passed is NULL");
205 		return QDF_STATUS_E_INVAL;
206 	}
207 
208 	mode = wlan_vdev_mlme_get_opmode(vdev);
209 	p2p_debug("vdev mode:%d", mode);
210 	if (mode != QDF_P2P_GO_MODE &&
211 	    mode != QDF_STA_MODE &&
212 	    mode != QDF_P2P_CLIENT_MODE &&
213 	    mode != QDF_P2P_DEVICE_MODE) {
214 		p2p_debug("won't create p2p vdev private object for mode %d",
215 			  mode);
216 		return QDF_STATUS_SUCCESS;
217 	}
218 
219 	p2p_vdev_obj =
220 		qdf_mem_malloc(sizeof(*p2p_vdev_obj));
221 	if (!p2p_vdev_obj)
222 		return QDF_STATUS_E_NOMEM;
223 
224 	p2p_vdev_obj->vdev = vdev;
225 	p2p_vdev_obj->noa_status = true;
226 	p2p_vdev_obj->non_p2p_peer_count = 0;
227 	p2p_init_random_mac_vdev(p2p_vdev_obj);
228 	qdf_mem_copy(p2p_vdev_obj->prev_action_frame_addr2,
229 		     wlan_vdev_mlme_get_macaddr(vdev), QDF_MAC_ADDR_SIZE);
230 
231 	status = wlan_objmgr_vdev_component_obj_attach(vdev,
232 				WLAN_UMAC_COMP_P2P, p2p_vdev_obj,
233 				QDF_STATUS_SUCCESS);
234 	if (status != QDF_STATUS_SUCCESS) {
235 		p2p_deinit_random_mac_vdev(p2p_vdev_obj);
236 		qdf_mem_free(p2p_vdev_obj);
237 		p2p_err("Failed to attach p2p component to vdev, %d",
238 			status);
239 		return status;
240 	}
241 
242 	p2p_debug("p2p vdev object create successful, %pK", p2p_vdev_obj);
243 
244 	return QDF_STATUS_SUCCESS;
245 }
246 
247 /**
248  * p2p_vdev_obj_destroy_notification() - Free per P2P vdev object
249  * @vdev: vdev context
250  * @data: Pointer to data
251  *
252  * This function gets called from object manager when vdev is being
253  * deleted and delete p2p vdev context.
254  *
255  * Return: QDF_STATUS_SUCCESS - in case of success
256  */
p2p_vdev_obj_destroy_notification(struct wlan_objmgr_vdev * vdev,void * data)257 static QDF_STATUS p2p_vdev_obj_destroy_notification(
258 	struct wlan_objmgr_vdev *vdev, void *data)
259 {
260 	struct p2p_vdev_priv_obj *p2p_vdev_obj;
261 	QDF_STATUS status;
262 	enum QDF_OPMODE mode;
263 
264 	if (!vdev) {
265 		p2p_err("vdev context passed is NULL");
266 		return QDF_STATUS_E_INVAL;
267 	}
268 
269 	mode = wlan_vdev_mlme_get_opmode(vdev);
270 	p2p_debug("vdev mode:%d", mode);
271 	if (mode != QDF_P2P_GO_MODE &&
272 	    mode != QDF_STA_MODE &&
273 	    mode != QDF_P2P_CLIENT_MODE &&
274 	    mode != QDF_P2P_DEVICE_MODE){
275 		p2p_debug("no p2p vdev private object for mode %d", mode);
276 		return QDF_STATUS_SUCCESS;
277 	}
278 
279 	p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
280 			WLAN_UMAC_COMP_P2P);
281 	if (!p2p_vdev_obj) {
282 		p2p_debug("p2p vdev object is NULL");
283 		return QDF_STATUS_SUCCESS;
284 	}
285 	p2p_deinit_random_mac_vdev(p2p_vdev_obj);
286 
287 	p2p_vdev_obj->vdev = NULL;
288 
289 	status = wlan_objmgr_vdev_component_obj_detach(vdev,
290 				WLAN_UMAC_COMP_P2P, p2p_vdev_obj);
291 	if (status != QDF_STATUS_SUCCESS) {
292 		p2p_err("Failed to detach p2p component, %d", status);
293 		return status;
294 	}
295 
296 	p2p_debug("destroy p2p vdev object, p2p vdev obj:%pK, noa info:%pK",
297 		p2p_vdev_obj, p2p_vdev_obj->noa_info);
298 
299 	if (p2p_vdev_obj->noa_info)
300 		qdf_mem_free(p2p_vdev_obj->noa_info);
301 
302 	qdf_mem_free(p2p_vdev_obj);
303 
304 	return QDF_STATUS_SUCCESS;
305 }
306 
307 /**
308  * p2p_peer_obj_create_notification() - manages peer details per vdev
309  * @peer: peer object
310  * @arg: Pointer to private argument - NULL
311  *
312  * This function gets called from object manager when peer is being
313  * created.
314  *
315  * Return: QDF_STATUS_SUCCESS - in case of success
316  */
p2p_peer_obj_create_notification(struct wlan_objmgr_peer * peer,void * arg)317 static QDF_STATUS p2p_peer_obj_create_notification(
318 	struct wlan_objmgr_peer *peer, void *arg)
319 {
320 	struct wlan_objmgr_vdev *vdev;
321 	enum QDF_OPMODE mode;
322 
323 	if (!peer) {
324 		p2p_err("peer context passed is NULL");
325 		return QDF_STATUS_E_INVAL;
326 	}
327 
328 	vdev = wlan_peer_get_vdev(peer);
329 	mode = wlan_vdev_mlme_get_opmode(vdev);
330 	if (mode != QDF_P2P_GO_MODE)
331 		return QDF_STATUS_SUCCESS;
332 
333 	p2p_debug("p2p peer object create successful");
334 
335 	return QDF_STATUS_SUCCESS;
336 }
337 
338 /**
339  * p2p_peer_obj_destroy_notification() - clears peer details per vdev
340  * @peer: peer object
341  * @arg: Pointer to private argument - NULL
342  *
343  * This function gets called from object manager when peer is being
344  * destroyed.
345  *
346  * Return: QDF_STATUS_SUCCESS - in case of success
347  */
p2p_peer_obj_destroy_notification(struct wlan_objmgr_peer * peer,void * arg)348 static QDF_STATUS p2p_peer_obj_destroy_notification(
349 	struct wlan_objmgr_peer *peer, void *arg)
350 {
351 	struct wlan_objmgr_vdev *vdev;
352 	struct p2p_vdev_priv_obj *p2p_vdev_obj;
353 	struct wlan_objmgr_psoc *psoc;
354 	enum QDF_OPMODE mode;
355 	enum wlan_peer_type peer_type;
356 	uint8_t vdev_id;
357 
358 	if (!peer) {
359 		p2p_err("peer context passed is NULL");
360 		return QDF_STATUS_E_INVAL;
361 	}
362 
363 	vdev = wlan_peer_get_vdev(peer);
364 	mode = wlan_vdev_mlme_get_opmode(vdev);
365 	if (mode != QDF_P2P_GO_MODE)
366 		return QDF_STATUS_SUCCESS;
367 
368 	p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
369 						WLAN_UMAC_COMP_P2P);
370 	psoc = wlan_vdev_get_psoc(vdev);
371 	if (!p2p_vdev_obj || !psoc) {
372 		p2p_debug("p2p_vdev_obj:%pK psoc:%pK", p2p_vdev_obj, psoc);
373 		return QDF_STATUS_E_INVAL;
374 	}
375 
376 	mode = wlan_vdev_mlme_get_opmode(vdev);
377 
378 	peer_type = wlan_peer_get_peer_type(peer);
379 
380 	if ((peer_type == WLAN_PEER_STA) && (mode == QDF_P2P_GO_MODE)) {
381 
382 		p2p_vdev_obj->non_p2p_peer_count--;
383 
384 		if (!p2p_vdev_obj->non_p2p_peer_count &&
385 		    (p2p_vdev_obj->noa_status == false)) {
386 
387 			vdev_id = wlan_vdev_get_id(vdev);
388 
389 			if (ucfg_p2p_set_noa(psoc, vdev_id,
390 				 false)	== QDF_STATUS_SUCCESS)
391 				p2p_vdev_obj->noa_status = true;
392 			else
393 				p2p_vdev_obj->noa_status = false;
394 
395 			p2p_debug("Non p2p peer disconnected from GO,NOA status: %d.",
396 				p2p_vdev_obj->noa_status);
397 		}
398 		p2p_debug("Non P2P peer count: %d",
399 			   p2p_vdev_obj->non_p2p_peer_count);
400 	}
401 	p2p_debug("p2p peer object destroy successful");
402 
403 	return QDF_STATUS_SUCCESS;
404 }
405 
406 /**
407  * p2p_send_noa_to_pe() - send noa information to pe
408  * @noa_info: vdev context
409  *
410  * This function sends noa information to pe since MCL layer need noa
411  * event.
412  *
413  * Return: QDF_STATUS_SUCCESS - in case of success
414  */
p2p_send_noa_to_pe(struct p2p_noa_info * noa_info)415 static QDF_STATUS p2p_send_noa_to_pe(struct p2p_noa_info *noa_info)
416 {
417 	struct p2p_noa_attr *noa_attr;
418 	struct scheduler_msg msg = {0};
419 	QDF_STATUS status;
420 
421 	if (!noa_info) {
422 		p2p_err("noa info is null");
423 		return QDF_STATUS_E_INVAL;
424 	}
425 
426 	noa_attr = qdf_mem_malloc(sizeof(*noa_attr));
427 	if (!noa_attr)
428 		return QDF_STATUS_E_NOMEM;
429 
430 	noa_attr->index = noa_info->index;
431 	noa_attr->opps_ps = noa_info->opps_ps;
432 	noa_attr->ct_win = noa_info->ct_window;
433 	if (!noa_info->num_desc) {
434 		p2p_debug("Zero noa descriptors");
435 	} else {
436 		p2p_debug("%d noa descriptors", noa_info->num_desc);
437 
438 		noa_attr->noa1_count =
439 			noa_info->noa_desc[0].type_count;
440 		noa_attr->noa1_duration =
441 			noa_info->noa_desc[0].duration;
442 		noa_attr->noa1_interval =
443 			noa_info->noa_desc[0].interval;
444 		noa_attr->noa1_start_time =
445 			noa_info->noa_desc[0].start_time;
446 		if (noa_info->num_desc > 1) {
447 			noa_attr->noa2_count =
448 				noa_info->noa_desc[1].type_count;
449 			noa_attr->noa2_duration =
450 				noa_info->noa_desc[1].duration;
451 			noa_attr->noa2_interval =
452 				noa_info->noa_desc[1].interval;
453 			noa_attr->noa2_start_time =
454 				noa_info->noa_desc[1].start_time;
455 		}
456 	}
457 
458 	p2p_debug("Sending P2P_NOA_ATTR_IND to pe");
459 
460 	msg.type = P2P_NOA_ATTR_IND;
461 	msg.bodyval = 0;
462 	msg.bodyptr = noa_attr;
463 	status = scheduler_post_message(QDF_MODULE_ID_P2P,
464 					QDF_MODULE_ID_P2P,
465 					QDF_MODULE_ID_PE,
466 					&msg);
467 	if (QDF_IS_STATUS_ERROR(status)) {
468 		qdf_mem_free(noa_attr);
469 		p2p_err("post msg fail:%d", status);
470 	}
471 
472 	return status;
473 }
474 
475 /**
476  * process_peer_for_noa() - disable NoA
477  * @vdev: vdev object
478  * @psoc: soc object
479  * @peer: peer object
480  *
481  * This function disables NoA
482  *
483  *
484  * Return: QDF_STATUS
485  */
process_peer_for_noa(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_peer * peer)486 static QDF_STATUS process_peer_for_noa(struct wlan_objmgr_vdev *vdev,
487 				struct wlan_objmgr_psoc *psoc,
488 				struct wlan_objmgr_peer *peer)
489 {
490 	struct p2p_vdev_priv_obj *p2p_vdev_obj = NULL;
491 	enum QDF_OPMODE mode;
492 	enum wlan_peer_type peer_type;
493 	bool disable_noa;
494 	uint8_t vdev_id;
495 
496 	if (!vdev || !psoc || !peer) {
497 		p2p_err("vdev:%pK psoc:%pK peer:%pK", vdev, psoc, peer);
498 		return QDF_STATUS_E_INVAL;
499 	}
500 	p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
501 						WLAN_UMAC_COMP_P2P);
502 	if (!p2p_vdev_obj)
503 		return QDF_STATUS_E_INVAL;
504 
505 	mode = wlan_vdev_mlme_get_opmode(vdev);
506 
507 	peer_type = wlan_peer_get_peer_type(peer);
508 	if (peer_type == WLAN_PEER_STA)
509 		p2p_vdev_obj->non_p2p_peer_count++;
510 
511 	disable_noa = ((mode == QDF_P2P_GO_MODE)
512 			&& p2p_vdev_obj->non_p2p_peer_count
513 			&& p2p_vdev_obj->noa_status);
514 
515 	if (disable_noa && (peer_type == WLAN_PEER_STA)) {
516 
517 		vdev_id = wlan_vdev_get_id(vdev);
518 
519 		if (ucfg_p2p_set_noa(psoc, vdev_id,
520 				true) == QDF_STATUS_SUCCESS) {
521 			p2p_vdev_obj->noa_status = false;
522 		} else {
523 			p2p_vdev_obj->noa_status = true;
524 		}
525 		p2p_debug("NoA status: %d", p2p_vdev_obj->noa_status);
526 	}
527 	p2p_debug("process_peer_for_noa");
528 
529 	return QDF_STATUS_SUCCESS;
530 }
531 
532 /**
533  * p2p_object_init_params() - init parameters for p2p object
534  * @psoc:        pointer to psoc object
535  * @p2p_soc_obj: pointer to p2p psoc object
536  *
537  * This function init parameters for p2p object
538  */
p2p_object_init_params(struct wlan_objmgr_psoc * psoc,struct p2p_soc_priv_obj * p2p_soc_obj)539 static QDF_STATUS p2p_object_init_params(
540 	struct wlan_objmgr_psoc *psoc,
541 	struct p2p_soc_priv_obj *p2p_soc_obj)
542 {
543 	if (!psoc || !p2p_soc_obj) {
544 		p2p_err("invalid param");
545 		return QDF_STATUS_E_INVAL;
546 	}
547 
548 	p2p_soc_obj->param.go_keepalive_period =
549 			cfg_get(psoc, CFG_GO_KEEP_ALIVE_PERIOD);
550 	p2p_soc_obj->param.go_link_monitor_period =
551 			cfg_get(psoc, CFG_GO_LINK_MONITOR_PERIOD);
552 	p2p_soc_obj->param.p2p_device_addr_admin =
553 			cfg_get(psoc, CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED);
554 	p2p_soc_obj->param.is_random_seq_num_enabled =
555 			cfg_get(psoc, CFG_ACTION_FRAME_RANDOM_SEQ_NUM_ENABLED);
556 	p2p_soc_obj->param.indoor_channel_support =
557 			cfg_get(psoc, CFG_P2P_GO_ON_5GHZ_INDOOR_CHANNEL);
558 	p2p_soc_obj->param.go_ignore_non_p2p_probe_req =
559 			cfg_get(psoc, CFG_GO_IGNORE_NON_P2P_PROBE_REQ);
560 
561 	return QDF_STATUS_SUCCESS;
562 }
563 
564 #ifdef WLAN_FEATURE_P2P_DEBUG
565 /**
566  * wlan_p2p_init_connection_status() - init connection status
567  * @p2p_soc_obj: pointer to p2p psoc object
568  *
569  * This function initial p2p connection status.
570  *
571  * Return: None
572  */
wlan_p2p_init_connection_status(struct p2p_soc_priv_obj * p2p_soc_obj)573 static void wlan_p2p_init_connection_status(
574 		struct p2p_soc_priv_obj *p2p_soc_obj)
575 {
576 	if (!p2p_soc_obj) {
577 		p2p_err("invalid p2p soc obj");
578 		return;
579 	}
580 
581 	p2p_soc_obj->connection_status = P2P_NOT_ACTIVE;
582 }
583 #else
wlan_p2p_init_connection_status(struct p2p_soc_priv_obj * p2p_soc_obj)584 static void wlan_p2p_init_connection_status(
585 		struct p2p_soc_priv_obj *p2p_soc_obj)
586 {
587 }
588 #endif /* WLAN_FEATURE_P2P_DEBUG */
589 
p2p_component_init(void)590 QDF_STATUS p2p_component_init(void)
591 {
592 	QDF_STATUS status;
593 
594 	status = wlan_objmgr_register_psoc_create_handler(
595 				WLAN_UMAC_COMP_P2P,
596 				p2p_psoc_obj_create_notification,
597 				NULL);
598 	if (status != QDF_STATUS_SUCCESS) {
599 		p2p_err("Failed to register p2p obj create handler");
600 		goto err_reg_psoc_create;
601 	}
602 
603 	status = wlan_objmgr_register_psoc_destroy_handler(
604 				WLAN_UMAC_COMP_P2P,
605 				p2p_psoc_obj_destroy_notification,
606 				NULL);
607 	if (status != QDF_STATUS_SUCCESS) {
608 		p2p_err("Failed to register p2p obj delete handler");
609 		goto err_reg_psoc_delete;
610 	}
611 
612 	status = wlan_objmgr_register_vdev_create_handler(
613 				WLAN_UMAC_COMP_P2P,
614 				p2p_vdev_obj_create_notification,
615 				NULL);
616 	if (status != QDF_STATUS_SUCCESS) {
617 		p2p_err("Failed to register p2p vdev create handler");
618 		goto err_reg_vdev_create;
619 	}
620 
621 	status = wlan_objmgr_register_vdev_destroy_handler(
622 				WLAN_UMAC_COMP_P2P,
623 				p2p_vdev_obj_destroy_notification,
624 				NULL);
625 	if (status != QDF_STATUS_SUCCESS) {
626 		p2p_err("Failed to register p2p vdev delete handler");
627 		goto err_reg_vdev_delete;
628 	}
629 
630 	status = wlan_objmgr_register_peer_create_handler(
631 				WLAN_UMAC_COMP_P2P,
632 				p2p_peer_obj_create_notification,
633 				NULL);
634 	if (status != QDF_STATUS_SUCCESS) {
635 		p2p_err("Failed to register p2p peer create handler");
636 		goto err_reg_peer_create;
637 	}
638 
639 	status = wlan_objmgr_register_peer_destroy_handler(
640 				WLAN_UMAC_COMP_P2P,
641 				p2p_peer_obj_destroy_notification,
642 				NULL);
643 	if (status != QDF_STATUS_SUCCESS) {
644 		p2p_err("Failed to register p2p peer destroy handler");
645 		goto err_reg_peer_destroy;
646 	}
647 
648 	p2p_debug("Register p2p obj handler successful");
649 
650 	return QDF_STATUS_SUCCESS;
651 err_reg_peer_destroy:
652 	wlan_objmgr_unregister_peer_create_handler(WLAN_UMAC_COMP_P2P,
653 			p2p_peer_obj_create_notification, NULL);
654 err_reg_peer_create:
655 	wlan_objmgr_unregister_vdev_destroy_handler(WLAN_UMAC_COMP_P2P,
656 			p2p_vdev_obj_destroy_notification, NULL);
657 err_reg_vdev_delete:
658 	wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_P2P,
659 			p2p_vdev_obj_create_notification, NULL);
660 err_reg_vdev_create:
661 	wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_P2P,
662 			p2p_psoc_obj_destroy_notification, NULL);
663 err_reg_psoc_delete:
664 	wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_P2P,
665 			p2p_psoc_obj_create_notification, NULL);
666 err_reg_psoc_create:
667 	return status;
668 }
669 
p2p_component_deinit(void)670 QDF_STATUS p2p_component_deinit(void)
671 {
672 	QDF_STATUS status;
673 	QDF_STATUS ret_status = QDF_STATUS_SUCCESS;
674 
675 	status = wlan_objmgr_unregister_vdev_create_handler(
676 				WLAN_UMAC_COMP_P2P,
677 				p2p_vdev_obj_create_notification,
678 				NULL);
679 	if (status != QDF_STATUS_SUCCESS) {
680 		p2p_err("Failed to unregister p2p vdev create handler, %d",
681 			status);
682 		ret_status = status;
683 	}
684 
685 	status = wlan_objmgr_unregister_vdev_destroy_handler(
686 				WLAN_UMAC_COMP_P2P,
687 				p2p_vdev_obj_destroy_notification,
688 				NULL);
689 	if (status != QDF_STATUS_SUCCESS) {
690 		p2p_err("Failed to unregister p2p vdev delete handler, %d",
691 			status);
692 		ret_status = status;
693 	}
694 
695 	status = wlan_objmgr_unregister_psoc_create_handler(
696 				WLAN_UMAC_COMP_P2P,
697 				p2p_psoc_obj_create_notification,
698 				NULL);
699 	if (status != QDF_STATUS_SUCCESS) {
700 		p2p_err("Failed to unregister p2p obj create handler, %d",
701 			status);
702 		ret_status = status;
703 	}
704 
705 	status = wlan_objmgr_unregister_psoc_destroy_handler(
706 				WLAN_UMAC_COMP_P2P,
707 				p2p_psoc_obj_destroy_notification,
708 				NULL);
709 	if (status != QDF_STATUS_SUCCESS) {
710 		p2p_err("Failed to unregister p2p obj delete handler, %d",
711 			status);
712 		ret_status = status;
713 	}
714 
715 	p2p_debug("Unregister p2p obj handler complete");
716 
717 	return ret_status;
718 }
719 
p2p_psoc_object_open(struct wlan_objmgr_psoc * soc)720 QDF_STATUS p2p_psoc_object_open(struct wlan_objmgr_psoc *soc)
721 {
722 	QDF_STATUS status;
723 	struct p2p_soc_priv_obj *p2p_soc_obj;
724 
725 	if (!soc) {
726 		p2p_err("psoc context passed is NULL");
727 		return QDF_STATUS_E_INVAL;
728 	}
729 
730 	p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc,
731 			WLAN_UMAC_COMP_P2P);
732 	if (!p2p_soc_obj) {
733 		p2p_err("p2p soc private object is NULL");
734 		return QDF_STATUS_E_FAILURE;
735 	}
736 
737 	p2p_object_init_params(soc, p2p_soc_obj);
738 	qdf_list_create(&p2p_soc_obj->roc_q, MAX_QUEUE_LENGTH);
739 	qdf_list_create(&p2p_soc_obj->tx_q_roc, MAX_QUEUE_LENGTH);
740 	qdf_list_create(&p2p_soc_obj->tx_q_ack, MAX_QUEUE_LENGTH);
741 
742 	status = qdf_event_create(&p2p_soc_obj->cleanup_roc_done);
743 	if (status != QDF_STATUS_SUCCESS) {
744 		p2p_err("failed to create cleanup roc done event");
745 		goto fail_cleanup_roc;
746 	}
747 
748 	status = qdf_event_create(&p2p_soc_obj->cleanup_tx_done);
749 	if (status != QDF_STATUS_SUCCESS) {
750 		p2p_err("failed to create cleanup roc done event");
751 		goto fail_cleanup_tx;
752 	}
753 
754 	qdf_runtime_lock_init(&p2p_soc_obj->roc_runtime_lock);
755 	p2p_soc_obj->cur_roc_vdev_id = P2P_INVALID_VDEV_ID;
756 	qdf_idr_create(&p2p_soc_obj->p2p_idr);
757 
758 	p2p_debug("p2p psoc object open successful");
759 
760 	return QDF_STATUS_SUCCESS;
761 
762 fail_cleanup_tx:
763 	qdf_event_destroy(&p2p_soc_obj->cleanup_roc_done);
764 
765 fail_cleanup_roc:
766 	qdf_list_destroy(&p2p_soc_obj->tx_q_ack);
767 	qdf_list_destroy(&p2p_soc_obj->tx_q_roc);
768 	qdf_list_destroy(&p2p_soc_obj->roc_q);
769 
770 	return status;
771 }
772 
p2p_psoc_object_close(struct wlan_objmgr_psoc * soc)773 QDF_STATUS p2p_psoc_object_close(struct wlan_objmgr_psoc *soc)
774 {
775 	struct p2p_soc_priv_obj *p2p_soc_obj;
776 
777 	if (!soc) {
778 		p2p_err("psoc context passed is NULL");
779 		return QDF_STATUS_E_INVAL;
780 	}
781 
782 	p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc,
783 			WLAN_UMAC_COMP_P2P);
784 	if (!p2p_soc_obj) {
785 		p2p_err("p2p soc object is NULL");
786 		return QDF_STATUS_E_FAILURE;
787 	}
788 
789 	qdf_idr_destroy(&p2p_soc_obj->p2p_idr);
790 	qdf_runtime_lock_deinit(&p2p_soc_obj->roc_runtime_lock);
791 	qdf_event_destroy(&p2p_soc_obj->cleanup_tx_done);
792 	qdf_event_destroy(&p2p_soc_obj->cleanup_roc_done);
793 	qdf_list_destroy(&p2p_soc_obj->tx_q_ack);
794 	qdf_list_destroy(&p2p_soc_obj->tx_q_roc);
795 	qdf_list_destroy(&p2p_soc_obj->roc_q);
796 
797 	p2p_debug("p2p psoc object close successful");
798 
799 	return QDF_STATUS_SUCCESS;
800 }
801 
802 #ifdef FEATURE_P2P_LISTEN_OFFLOAD
p2p_init_lo_event(struct p2p_start_param * start_param,struct p2p_start_param * req)803 static inline void p2p_init_lo_event(struct p2p_start_param *start_param,
804 				     struct p2p_start_param *req)
805 {
806 	start_param->lo_event_cb = req->lo_event_cb;
807 	start_param->lo_event_cb_data = req->lo_event_cb_data;
808 }
809 #else
p2p_init_lo_event(struct p2p_start_param * start_param,struct p2p_start_param * req)810 static inline void p2p_init_lo_event(struct p2p_start_param *start_param,
811 				     struct p2p_start_param *req)
812 {
813 }
814 #endif
815 
p2p_psoc_start(struct wlan_objmgr_psoc * soc,struct p2p_start_param * req)816 QDF_STATUS p2p_psoc_start(struct wlan_objmgr_psoc *soc,
817 	struct p2p_start_param *req)
818 {
819 	struct p2p_soc_priv_obj *p2p_soc_obj;
820 	struct p2p_start_param *start_param;
821 
822 	if (!soc) {
823 		p2p_err("psoc context passed is NULL");
824 		return QDF_STATUS_E_INVAL;
825 	}
826 
827 	p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc,
828 			WLAN_UMAC_COMP_P2P);
829 	if (!p2p_soc_obj) {
830 		p2p_err("P2P soc object is NULL");
831 		return QDF_STATUS_E_FAILURE;
832 	}
833 
834 	start_param = qdf_mem_malloc(sizeof(*start_param));
835 	if (!start_param)
836 		return QDF_STATUS_E_NOMEM;
837 
838 	start_param->rx_cb = req->rx_cb;
839 	start_param->rx_cb_data = req->rx_cb_data;
840 	start_param->event_cb = req->event_cb;
841 	start_param->event_cb_data = req->event_cb_data;
842 	start_param->tx_cnf_cb = req->tx_cnf_cb;
843 	start_param->tx_cnf_cb_data = req->tx_cnf_cb_data;
844 	p2p_init_lo_event(start_param, req);
845 	p2p_soc_obj->start_param = start_param;
846 
847 	wlan_p2p_init_connection_status(p2p_soc_obj);
848 
849 	/* register p2p lo stop and noa event */
850 	tgt_p2p_register_lo_ev_handler(soc);
851 	tgt_p2p_register_noa_ev_handler(soc);
852 	tgt_p2p_register_macaddr_rx_filter_evt_handler(soc, true);
853 	tgt_p2p_register_mcc_quota_ev_handler(soc, true);
854 	/* register scan request id */
855 	p2p_soc_obj->scan_req_id = wlan_scan_register_requester(
856 		soc, P2P_MODULE_NAME, tgt_p2p_scan_event_cb,
857 		p2p_soc_obj);
858 
859 	/* register rx action frame */
860 	p2p_mgmt_rx_action_ops(soc, true);
861 
862 	p2p_debug("p2p psoc start successful, scan request id:%d",
863 		p2p_soc_obj->scan_req_id);
864 
865 	return QDF_STATUS_SUCCESS;
866 }
867 
p2p_psoc_stop(struct wlan_objmgr_psoc * soc)868 QDF_STATUS p2p_psoc_stop(struct wlan_objmgr_psoc *soc)
869 {
870 	struct p2p_soc_priv_obj *p2p_soc_obj;
871 	struct p2p_start_param *start_param;
872 
873 	if (!soc) {
874 		p2p_err("psoc context passed is NULL");
875 		return QDF_STATUS_E_INVAL;
876 	}
877 
878 	p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc,
879 			WLAN_UMAC_COMP_P2P);
880 	if (!p2p_soc_obj) {
881 		p2p_err("P2P soc object is NULL");
882 		return QDF_STATUS_E_FAILURE;
883 	}
884 
885 	start_param = p2p_soc_obj->start_param;
886 	p2p_soc_obj->start_param = NULL;
887 	if (!start_param) {
888 		p2p_err("start parameters is NULL");
889 		return QDF_STATUS_E_FAILURE;
890 	}
891 
892 	/* unregister rx action frame */
893 	p2p_mgmt_rx_action_ops(soc, false);
894 
895 	/* clean up queue of p2p psoc private object */
896 	p2p_cleanup_tx_sync(p2p_soc_obj, NULL);
897 	p2p_cleanup_roc(p2p_soc_obj, NULL, true);
898 
899 	/* unrgister scan request id*/
900 	wlan_scan_unregister_requester(soc, p2p_soc_obj->scan_req_id);
901 
902 	tgt_p2p_register_mcc_quota_ev_handler(soc, false);
903 	/* unregister p2p lo stop and noa event */
904 	tgt_p2p_register_macaddr_rx_filter_evt_handler(soc, false);
905 	tgt_p2p_unregister_lo_ev_handler(soc);
906 	tgt_p2p_unregister_noa_ev_handler(soc);
907 
908 	start_param->rx_cb = NULL;
909 	start_param->rx_cb_data = NULL;
910 	start_param->event_cb = NULL;
911 	start_param->event_cb_data = NULL;
912 	start_param->tx_cnf_cb = NULL;
913 	start_param->tx_cnf_cb_data = NULL;
914 	qdf_mem_free(start_param);
915 
916 	p2p_debug("p2p psoc stop successful");
917 
918 	return QDF_STATUS_SUCCESS;
919 }
920 
p2p_process_cmd(struct scheduler_msg * msg)921 QDF_STATUS p2p_process_cmd(struct scheduler_msg *msg)
922 {
923 	QDF_STATUS status;
924 
925 	p2p_debug("msg type %d, %s", msg->type,
926 		p2p_get_cmd_type_str(msg->type));
927 
928 	if (!(msg->bodyptr)) {
929 		p2p_err("Invalid message body");
930 		return QDF_STATUS_E_INVAL;
931 	}
932 	switch (msg->type) {
933 	case P2P_ROC_REQ:
934 		status = p2p_process_roc_req(
935 				(struct p2p_roc_context *)
936 				msg->bodyptr);
937 		break;
938 	case P2P_CANCEL_ROC_REQ:
939 		status = p2p_process_cancel_roc_req(
940 				(struct cancel_roc_context *)
941 				msg->bodyptr);
942 		qdf_mem_free(msg->bodyptr);
943 		break;
944 	case P2P_MGMT_TX:
945 		status = p2p_process_mgmt_tx(
946 				(struct tx_action_context *)
947 				msg->bodyptr);
948 		break;
949 	case P2P_MGMT_TX_CANCEL:
950 		status = p2p_process_mgmt_tx_cancel(
951 				(struct cancel_roc_context *)
952 				msg->bodyptr);
953 		qdf_mem_free(msg->bodyptr);
954 		break;
955 	case P2P_CLEANUP_ROC:
956 		status = p2p_process_cleanup_roc_queue(
957 				(struct p2p_cleanup_param *)
958 				msg->bodyptr);
959 		qdf_mem_free(msg->bodyptr);
960 		break;
961 	case P2P_CLEANUP_TX:
962 		status = p2p_process_cleanup_tx_queue(
963 				(struct p2p_cleanup_param *)
964 				msg->bodyptr);
965 		qdf_mem_free(msg->bodyptr);
966 		break;
967 	case P2P_SET_RANDOM_MAC:
968 		status = p2p_process_set_rand_mac(msg->bodyptr);
969 		qdf_mem_free(msg->bodyptr);
970 		break;
971 
972 	default:
973 		p2p_err("drop unexpected message received %d",
974 			msg->type);
975 		status = QDF_STATUS_E_INVAL;
976 		break;
977 	}
978 
979 	return status;
980 }
981 
p2p_process_evt(struct scheduler_msg * msg)982 QDF_STATUS p2p_process_evt(struct scheduler_msg *msg)
983 {
984 	QDF_STATUS status;
985 
986 	p2p_debug("msg type %d, %s", msg->type,
987 		p2p_get_event_type_str(msg->type));
988 
989 	if (!(msg->bodyptr)) {
990 		p2p_err("Invalid message body");
991 		return QDF_STATUS_E_INVAL;
992 	}
993 
994 	switch (msg->type) {
995 	case P2P_EVENT_MGMT_TX_ACK_CNF:
996 		status = p2p_process_mgmt_tx_ack_cnf(
997 				(struct p2p_tx_conf_event *)
998 				msg->bodyptr);
999 		break;
1000 	case P2P_EVENT_RX_MGMT:
1001 		status  = p2p_process_rx_mgmt(
1002 				(struct p2p_rx_mgmt_event *)
1003 				msg->bodyptr);
1004 		break;
1005 	case P2P_EVENT_LO_STOPPED:
1006 		status = p2p_process_lo_stop(
1007 				(struct p2p_lo_stop_event *)
1008 				msg->bodyptr);
1009 		break;
1010 	case P2P_EVENT_NOA:
1011 		status = p2p_process_noa(
1012 				(struct p2p_noa_event *)
1013 				msg->bodyptr);
1014 		break;
1015 	case P2P_EVENT_ADD_MAC_RSP:
1016 		status = p2p_process_set_rand_mac_rsp(
1017 				(struct p2p_mac_filter_rsp *)
1018 				msg->bodyptr);
1019 		break;
1020 	default:
1021 		p2p_err("Drop unexpected message received %d",
1022 			msg->type);
1023 		status = QDF_STATUS_E_INVAL;
1024 		break;
1025 	}
1026 
1027 	qdf_mem_free(msg->bodyptr);
1028 	msg->bodyptr = NULL;
1029 
1030 	return status;
1031 }
1032 
p2p_msg_flush_callback(struct scheduler_msg * msg)1033 QDF_STATUS p2p_msg_flush_callback(struct scheduler_msg *msg)
1034 {
1035 	struct tx_action_context *tx_action;
1036 
1037 	if (!msg || !(msg->bodyptr)) {
1038 		p2p_err("invalid msg");
1039 		return QDF_STATUS_E_INVAL;
1040 	}
1041 
1042 	p2p_debug("flush msg, type:%d", msg->type);
1043 	switch (msg->type) {
1044 	case P2P_MGMT_TX:
1045 		tx_action = (struct tx_action_context *)msg->bodyptr;
1046 		qdf_mem_free(tx_action->buf);
1047 		qdf_mem_free(tx_action);
1048 		break;
1049 	default:
1050 		qdf_mem_free(msg->bodyptr);
1051 		break;
1052 	}
1053 
1054 	return QDF_STATUS_SUCCESS;
1055 }
1056 
p2p_event_flush_callback(struct scheduler_msg * msg)1057 QDF_STATUS p2p_event_flush_callback(struct scheduler_msg *msg)
1058 {
1059 	struct p2p_noa_event *noa_event;
1060 	struct p2p_rx_mgmt_event *rx_mgmt_event;
1061 	struct p2p_tx_conf_event *tx_conf_event;
1062 	struct p2p_lo_stop_event *lo_stop_event;
1063 
1064 	if (!msg || !(msg->bodyptr)) {
1065 		p2p_err("invalid msg");
1066 		return QDF_STATUS_E_INVAL;
1067 	}
1068 
1069 	p2p_debug("flush event, type:%d", msg->type);
1070 	switch (msg->type) {
1071 	case P2P_EVENT_NOA:
1072 		noa_event = (struct p2p_noa_event *)msg->bodyptr;
1073 		qdf_mem_free(noa_event->noa_info);
1074 		qdf_mem_free(noa_event);
1075 		break;
1076 	case P2P_EVENT_RX_MGMT:
1077 		rx_mgmt_event = (struct p2p_rx_mgmt_event *)msg->bodyptr;
1078 		qdf_mem_free(rx_mgmt_event->rx_mgmt);
1079 		qdf_mem_free(rx_mgmt_event);
1080 		break;
1081 	case P2P_EVENT_MGMT_TX_ACK_CNF:
1082 		tx_conf_event = (struct p2p_tx_conf_event *)msg->bodyptr;
1083 		qdf_nbuf_free(tx_conf_event->nbuf);
1084 		qdf_mem_free(tx_conf_event);
1085 		break;
1086 	case P2P_EVENT_LO_STOPPED:
1087 		lo_stop_event = (struct p2p_lo_stop_event *)msg->bodyptr;
1088 		qdf_mem_free(lo_stop_event->lo_event);
1089 		qdf_mem_free(lo_stop_event);
1090 		break;
1091 	default:
1092 		qdf_mem_free(msg->bodyptr);
1093 		break;
1094 	}
1095 
1096 	return QDF_STATUS_SUCCESS;
1097 }
1098 
p2p_check_oui_and_force_1x1(uint8_t * assoc_ie,uint32_t assoc_ie_len)1099 bool p2p_check_oui_and_force_1x1(uint8_t *assoc_ie, uint32_t assoc_ie_len)
1100 {
1101 	const uint8_t *vendor_ie, *p2p_ie, *pos;
1102 	uint8_t rem_len, attr;
1103 	uint16_t attr_len;
1104 
1105 	vendor_ie = (uint8_t *)p2p_get_p2pie_ptr(assoc_ie, assoc_ie_len);
1106 	if (!vendor_ie) {
1107 		p2p_debug("P2P IE not found");
1108 		return false;
1109 	}
1110 
1111 	rem_len = vendor_ie[1];
1112 	if (rem_len < (2 + OUI_SIZE_P2P) || rem_len > WLAN_MAX_IE_LEN) {
1113 		p2p_err("Invalid IE len %d", rem_len);
1114 		return false;
1115 	}
1116 
1117 	p2p_ie = vendor_ie + HEADER_LEN_P2P_IE;
1118 	rem_len -= OUI_SIZE_P2P;
1119 
1120 	while (rem_len) {
1121 		attr = p2p_ie[0];
1122 		attr_len = LE_READ_2(&p2p_ie[1]);
1123 		if (attr_len > rem_len)  {
1124 			p2p_err("Invalid len %d for elem:%d", attr_len, attr);
1125 			return false;
1126 		}
1127 
1128 		switch (attr) {
1129 		case P2P_ATTR_CAPABILITY:
1130 		case P2P_ATTR_DEVICE_ID:
1131 		case P2P_ATTR_GROUP_OWNER_INTENT:
1132 		case P2P_ATTR_STATUS:
1133 		case P2P_ATTR_LISTEN_CHANNEL:
1134 		case P2P_ATTR_OPERATING_CHANNEL:
1135 		case P2P_ATTR_GROUP_INFO:
1136 		case P2P_ATTR_MANAGEABILITY:
1137 		case P2P_ATTR_CHANNEL_LIST:
1138 			break;
1139 
1140 		case P2P_ATTR_DEVICE_INFO:
1141 			if (attr_len < (QDF_MAC_ADDR_SIZE +
1142 					MAX_CONFIG_METHODS_LEN + 8 +
1143 					DEVICE_CATEGORY_MAX_LEN)) {
1144 				p2p_err("Invalid Device info attr len %d",
1145 					attr_len);
1146 				return false;
1147 			}
1148 
1149 			/* move by attr id and 2 bytes of attr len */
1150 			pos = p2p_ie + 3;
1151 
1152 			/*
1153 			 * the P2P Device info is of format:
1154 			 * attr_id - 1 byte
1155 			 * attr_len - 2 bytes
1156 			 * device mac addr - 6 bytes
1157 			 * config methods - 2 bytes
1158 			 * primary device type - 8bytes
1159 			 *  -primary device type category - 1 byte
1160 			 *  -primary device type oui - 4bytes
1161 			 * number of secondary device type - 2 bytes
1162 			 */
1163 			pos += ETH_ALEN + MAX_CONFIG_METHODS_LEN +
1164 			       DEVICE_CATEGORY_MAX_LEN;
1165 
1166 			if (!qdf_mem_cmp(pos, P2P_1X1_WAR_OUI,
1167 					 P2P_1X1_OUI_LEN))
1168 				return true;
1169 
1170 			break;
1171 		default:
1172 			p2p_err("Invalid P2P attribute");
1173 			break;
1174 		}
1175 		p2p_ie += (3 + attr_len);
1176 		rem_len -= (3 + attr_len);
1177 	}
1178 
1179 	return false;
1180 }
1181 
1182 #ifdef FEATURE_P2P_LISTEN_OFFLOAD
p2p_process_lo_stop(struct p2p_lo_stop_event * lo_stop_event)1183 QDF_STATUS p2p_process_lo_stop(
1184 	struct p2p_lo_stop_event *lo_stop_event)
1185 {
1186 	struct p2p_lo_event *lo_evt;
1187 	struct p2p_soc_priv_obj *p2p_soc_obj;
1188 	struct p2p_start_param *start_param;
1189 
1190 	if (!lo_stop_event) {
1191 		p2p_err("invalid lo stop event");
1192 		return QDF_STATUS_E_INVAL;
1193 	}
1194 
1195 	lo_evt = lo_stop_event->lo_event;
1196 	if (!lo_evt) {
1197 		p2p_err("invalid lo event");
1198 		return QDF_STATUS_E_INVAL;
1199 	}
1200 
1201 	p2p_soc_obj = lo_stop_event->p2p_soc_obj;
1202 
1203 	p2p_debug("vdev_id %d, reason %d",
1204 		lo_evt->vdev_id, lo_evt->reason_code);
1205 
1206 	if (!p2p_soc_obj || !(p2p_soc_obj->start_param)) {
1207 		p2p_err("Invalid p2p soc object or start parameters");
1208 		qdf_mem_free(lo_evt);
1209 		return QDF_STATUS_E_INVAL;
1210 	}
1211 	start_param = p2p_soc_obj->start_param;
1212 	if (start_param->lo_event_cb)
1213 		start_param->lo_event_cb(
1214 			start_param->lo_event_cb_data, lo_evt);
1215 	else
1216 		p2p_err("Invalid p2p soc obj or hdd lo event callback");
1217 
1218 	qdf_mem_free(lo_evt);
1219 
1220 	return QDF_STATUS_SUCCESS;
1221 }
1222 #endif
1223 
p2p_process_noa(struct p2p_noa_event * noa_event)1224 QDF_STATUS p2p_process_noa(struct p2p_noa_event *noa_event)
1225 {
1226 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1227 	struct p2p_noa_info *noa_info;
1228 	struct p2p_vdev_priv_obj *p2p_vdev_obj;
1229 	struct p2p_soc_priv_obj *p2p_soc_obj;
1230 	struct wlan_objmgr_vdev *vdev;
1231 	struct wlan_objmgr_psoc *psoc;
1232 	enum QDF_OPMODE mode;
1233 
1234 	if (!noa_event) {
1235 		p2p_err("invalid noa event");
1236 		return QDF_STATUS_E_INVAL;
1237 	}
1238 	noa_info = noa_event->noa_info;
1239 	p2p_soc_obj = noa_event->p2p_soc_obj;
1240 	psoc = p2p_soc_obj->soc;
1241 
1242 	p2p_debug("psoc:%pK, index:%d, opps_ps:%d, ct_window:%d, num_desc:%d, vdev_id:%d",
1243 		psoc, noa_info->index, noa_info->opps_ps,
1244 		noa_info->ct_window, noa_info->num_desc,
1245 		noa_info->vdev_id);
1246 
1247 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
1248 			noa_info->vdev_id, WLAN_P2P_ID);
1249 	if (!vdev) {
1250 		p2p_err("vdev obj is NULL");
1251 		qdf_mem_free(noa_event->noa_info);
1252 		return QDF_STATUS_E_INVAL;
1253 	}
1254 
1255 	mode = wlan_vdev_mlme_get_opmode(vdev);
1256 	p2p_debug("vdev mode:%d", mode);
1257 	if (mode != QDF_P2P_GO_MODE) {
1258 		p2p_err("invalid p2p vdev mode:%d", mode);
1259 		status = QDF_STATUS_E_INVAL;
1260 		goto fail;
1261 	}
1262 
1263 	/* must send noa to pe since of limitation*/
1264 	p2p_send_noa_to_pe(noa_info);
1265 
1266 	p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
1267 			WLAN_UMAC_COMP_P2P);
1268 	if (!(p2p_vdev_obj->noa_info)) {
1269 		p2p_vdev_obj->noa_info =
1270 			qdf_mem_malloc(sizeof(struct p2p_noa_info));
1271 		if (!(p2p_vdev_obj->noa_info)) {
1272 			status = QDF_STATUS_E_NOMEM;
1273 			goto fail;
1274 		}
1275 	}
1276 	qdf_mem_copy(p2p_vdev_obj->noa_info, noa_info,
1277 		sizeof(struct p2p_noa_info));
1278 fail:
1279 	qdf_mem_free(noa_event->noa_info);
1280 	wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
1281 
1282 	return status;
1283 }
1284 
p2p_peer_authorized(struct wlan_objmgr_vdev * vdev,uint8_t * mac_addr)1285 void p2p_peer_authorized(struct wlan_objmgr_vdev *vdev, uint8_t *mac_addr)
1286 {
1287 	QDF_STATUS status;
1288 	struct wlan_objmgr_psoc *psoc;
1289 	struct wlan_objmgr_peer *peer;
1290 	uint8_t pdev_id;
1291 
1292 	if (!vdev) {
1293 		p2p_err("vdev:%pK", vdev);
1294 		return;
1295 	}
1296 	psoc = wlan_vdev_get_psoc(vdev);
1297 	if (!psoc) {
1298 		p2p_err("psoc:%pK", psoc);
1299 		return;
1300 	}
1301 	pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev));
1302 	peer = wlan_objmgr_get_peer(psoc, pdev_id,  mac_addr, WLAN_P2P_ID);
1303 	if (!peer) {
1304 		p2p_debug("peer info not found");
1305 		return;
1306 	}
1307 	status = process_peer_for_noa(vdev, psoc, peer);
1308 	wlan_objmgr_peer_release_ref(peer, WLAN_P2P_ID);
1309 
1310 	if (status != QDF_STATUS_SUCCESS)
1311 		return;
1312 
1313 	p2p_debug("peer is authorized");
1314 }
1315 
1316 #ifdef WLAN_FEATURE_P2P_DEBUG
1317 
p2p_status_update(struct p2p_soc_priv_obj * p2p_soc_obj,enum p2p_connection_status status)1318 void p2p_status_update(struct p2p_soc_priv_obj *p2p_soc_obj,
1319 		       enum p2p_connection_status status)
1320 {
1321 	 p2p_soc_obj->connection_status = status;
1322 }
1323 
1324 static struct p2p_soc_priv_obj *
get_p2p_soc_obj_by_vdev(struct wlan_objmgr_vdev * vdev)1325 get_p2p_soc_obj_by_vdev(struct wlan_objmgr_vdev *vdev)
1326 {
1327 	struct p2p_soc_priv_obj *p2p_soc_obj;
1328 	struct wlan_objmgr_psoc *soc;
1329 
1330 	if (!vdev) {
1331 		p2p_err("vdev context passed is NULL");
1332 		return NULL;
1333 	}
1334 
1335 	soc = wlan_vdev_get_psoc(vdev);
1336 	if (!soc) {
1337 		p2p_err("soc context is NULL");
1338 		return NULL;
1339 	}
1340 
1341 	p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc,
1342 			WLAN_UMAC_COMP_P2P);
1343 	if (!p2p_soc_obj)
1344 		p2p_err("P2P soc context is NULL");
1345 
1346 	return p2p_soc_obj;
1347 }
1348 
p2p_status_scan(struct wlan_objmgr_vdev * vdev)1349 QDF_STATUS p2p_status_scan(struct wlan_objmgr_vdev *vdev)
1350 {
1351 	struct p2p_soc_priv_obj *p2p_soc_obj;
1352 	enum QDF_OPMODE mode;
1353 
1354 	p2p_soc_obj = get_p2p_soc_obj_by_vdev(vdev);
1355 	if (!p2p_soc_obj) {
1356 		p2p_err("P2P soc context is NULL");
1357 		return QDF_STATUS_E_FAILURE;
1358 	}
1359 
1360 	mode = wlan_vdev_mlme_get_opmode(vdev);
1361 	if (mode != QDF_P2P_CLIENT_MODE &&
1362 	    mode != QDF_P2P_DEVICE_MODE) {
1363 		p2p_debug("this is not P2P CLIENT or DEVICE, mode:%d",
1364 			mode);
1365 		return QDF_STATUS_SUCCESS;
1366 	}
1367 
1368 	p2p_debug("connection status:%d", p2p_soc_obj->connection_status);
1369 	switch (p2p_soc_obj->connection_status) {
1370 	case P2P_GO_NEG_COMPLETED:
1371 	case P2P_GO_NEG_PROCESS:
1372 		p2p_status_update(p2p_soc_obj,
1373 				  P2P_CLIENT_CONNECTING_STATE_1);
1374 		p2p_debug("[P2P State] Changing state from Go nego completed to Connection is started");
1375 		p2p_debug("P2P Scanning is started for 8way Handshake");
1376 		break;
1377 	case P2P_CLIENT_DISCONNECTED_STATE:
1378 		p2p_status_update(p2p_soc_obj,
1379 				  P2P_CLIENT_CONNECTING_STATE_2);
1380 		p2p_debug("[P2P State] Changing state from Disconnected state to Connection is started");
1381 		p2p_debug("P2P Scanning is started for 4way Handshake");
1382 		break;
1383 	default:
1384 		break;
1385 	}
1386 
1387 	return QDF_STATUS_SUCCESS;
1388 }
1389 
p2p_status_connect(struct wlan_objmgr_vdev * vdev)1390 QDF_STATUS p2p_status_connect(struct wlan_objmgr_vdev *vdev)
1391 {
1392 	struct p2p_soc_priv_obj *p2p_soc_obj;
1393 	enum QDF_OPMODE mode;
1394 
1395 	p2p_soc_obj = get_p2p_soc_obj_by_vdev(vdev);
1396 	if (!p2p_soc_obj) {
1397 		p2p_err("P2P soc context is NULL");
1398 		return QDF_STATUS_E_FAILURE;
1399 	}
1400 
1401 	mode = wlan_vdev_mlme_get_opmode(vdev);
1402 	if (mode != QDF_P2P_CLIENT_MODE)
1403 		return QDF_STATUS_SUCCESS;
1404 
1405 	p2p_debug("connection status:%d", p2p_soc_obj->connection_status);
1406 	switch (p2p_soc_obj->connection_status) {
1407 	case P2P_CLIENT_CONNECTING_STATE_1:
1408 		p2p_status_update(p2p_soc_obj,
1409 				  P2P_CLIENT_CONNECTED_STATE_1);
1410 		p2p_debug("[P2P State] Changing state from Connecting state to Connected State for 8-way Handshake");
1411 		break;
1412 	case P2P_CLIENT_DISCONNECTED_STATE:
1413 		p2p_debug("No scan before 4-way handshake");
1414 		/*
1415 		 * since no scan before 4-way handshake and
1416 		 * won't enter state P2P_CLIENT_CONNECTING_STATE_2:
1417 		 */
1418 		fallthrough;
1419 	case P2P_CLIENT_CONNECTING_STATE_2:
1420 		p2p_status_update(p2p_soc_obj,
1421 				  P2P_CLIENT_COMPLETED_STATE);
1422 		p2p_debug("[P2P State] Changing state from Connecting state to P2P Client Connection Completed");
1423 		break;
1424 	default:
1425 		break;
1426 	}
1427 
1428 	return QDF_STATUS_SUCCESS;
1429 }
1430 
p2p_status_disconnect(struct wlan_objmgr_vdev * vdev)1431 QDF_STATUS p2p_status_disconnect(struct wlan_objmgr_vdev *vdev)
1432 {
1433 	struct p2p_soc_priv_obj *p2p_soc_obj;
1434 	enum QDF_OPMODE mode;
1435 
1436 	p2p_soc_obj = get_p2p_soc_obj_by_vdev(vdev);
1437 	if (!p2p_soc_obj) {
1438 		p2p_err("P2P soc context is NULL");
1439 		return QDF_STATUS_E_FAILURE;
1440 	}
1441 
1442 	mode = wlan_vdev_mlme_get_opmode(vdev);
1443 	if (mode != QDF_P2P_CLIENT_MODE)
1444 		return QDF_STATUS_SUCCESS;
1445 
1446 	p2p_debug("connection status:%d", p2p_soc_obj->connection_status);
1447 	switch (p2p_soc_obj->connection_status) {
1448 	case P2P_CLIENT_CONNECTED_STATE_1:
1449 		p2p_status_update(p2p_soc_obj,
1450 				  P2P_CLIENT_DISCONNECTED_STATE);
1451 		p2p_debug("[P2P State] 8 way Handshake completed and moved to disconnected state");
1452 		break;
1453 	case P2P_CLIENT_COMPLETED_STATE:
1454 		p2p_status_update(p2p_soc_obj, P2P_NOT_ACTIVE);
1455 		p2p_debug("[P2P State] P2P Client is removed and moved to inactive state");
1456 		break;
1457 	default:
1458 		break;
1459 	}
1460 
1461 	return QDF_STATUS_SUCCESS;
1462 }
1463 
p2p_status_start_bss(struct wlan_objmgr_vdev * vdev)1464 QDF_STATUS p2p_status_start_bss(struct wlan_objmgr_vdev *vdev)
1465 {
1466 	struct p2p_soc_priv_obj *p2p_soc_obj;
1467 	enum QDF_OPMODE mode;
1468 
1469 	p2p_soc_obj = get_p2p_soc_obj_by_vdev(vdev);
1470 	if (!p2p_soc_obj) {
1471 		p2p_err("P2P soc context is NULL");
1472 		return QDF_STATUS_E_FAILURE;
1473 	}
1474 
1475 	mode = wlan_vdev_mlme_get_opmode(vdev);
1476 	if (mode != QDF_P2P_GO_MODE) {
1477 		p2p_debug("this is not P2P GO, mode:%d", mode);
1478 		return QDF_STATUS_SUCCESS;
1479 	}
1480 
1481 	p2p_debug("connection status:%d", p2p_soc_obj->connection_status);
1482 	switch (p2p_soc_obj->connection_status) {
1483 	case P2P_GO_NEG_COMPLETED:
1484 		p2p_status_update(p2p_soc_obj,
1485 				  P2P_GO_COMPLETED_STATE);
1486 		p2p_debug("[P2P State] From Go nego completed to Non-autonomous Group started");
1487 		break;
1488 	case P2P_NOT_ACTIVE:
1489 		p2p_status_update(p2p_soc_obj,
1490 				  P2P_GO_COMPLETED_STATE);
1491 		p2p_debug("[P2P State] From Inactive to Autonomous Group started");
1492 		break;
1493 	default:
1494 		break;
1495 	}
1496 
1497 	return QDF_STATUS_SUCCESS;
1498 }
1499 
p2p_status_stop_bss(struct wlan_objmgr_vdev * vdev)1500 QDF_STATUS p2p_status_stop_bss(struct wlan_objmgr_vdev *vdev)
1501 {
1502 	struct p2p_soc_priv_obj *p2p_soc_obj;
1503 	enum QDF_OPMODE mode;
1504 
1505 	p2p_soc_obj = get_p2p_soc_obj_by_vdev(vdev);
1506 	if (!p2p_soc_obj) {
1507 		p2p_err("P2P soc context is NULL");
1508 		return QDF_STATUS_E_FAILURE;
1509 	}
1510 
1511 	mode = wlan_vdev_mlme_get_opmode(vdev);
1512 	if (mode != QDF_P2P_GO_MODE) {
1513 		p2p_debug("this is not P2P GO, mode:%d", mode);
1514 		return QDF_STATUS_SUCCESS;
1515 	}
1516 
1517 	p2p_debug("connection status:%d", p2p_soc_obj->connection_status);
1518 	if (p2p_soc_obj->connection_status == P2P_GO_COMPLETED_STATE) {
1519 		p2p_status_update(p2p_soc_obj, P2P_NOT_ACTIVE);
1520 		p2p_debug("[P2P State] From GO completed to Inactive state GO got removed");
1521 	}
1522 
1523 	return QDF_STATUS_SUCCESS;
1524 }
1525 
1526 #endif /* WLAN_FEATURE_P2P_DEBUG */
1527 
1528 #ifdef WLAN_FEATURE_P2P_P2P_STA
p2p_check_and_force_scc_go_plus_go(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev)1529 QDF_STATUS p2p_check_and_force_scc_go_plus_go(struct wlan_objmgr_psoc *psoc,
1530 					      struct wlan_objmgr_vdev *vdev)
1531 {
1532 	int go_count = 0;
1533 	uint32_t existing_chan_freq, chan_freq;
1534 	enum phy_ch_width existing_ch_width, ch_width;
1535 	uint8_t existing_vdev_id = WLAN_UMAC_VDEV_ID_MAX, vdev_id;
1536 	enum policy_mgr_con_mode existing_vdev_mode = PM_MAX_NUM_OF_MODE;
1537 	bool go_force_scc = false;
1538 
1539 	go_count = policy_mgr_mode_specific_connection_count(
1540 			psoc, PM_P2P_GO_MODE, NULL);
1541 	go_force_scc = policy_mgr_go_scc_enforced(psoc);
1542 	if (go_count > 1 && go_force_scc) {
1543 		vdev_id = wlan_vdev_get_id(vdev);
1544 		chan_freq = wlan_get_operation_chan_freq(vdev);
1545 		ch_width = vdev->vdev_mlme.bss_chan->ch_width;
1546 		p2p_debug("Current vdev_id %d, chan_freq %d and ch_width %d",
1547 			  vdev_id, chan_freq, ch_width);
1548 		existing_vdev_id = policy_mgr_fetch_existing_con_info(
1549 				psoc, vdev_id,
1550 				chan_freq,
1551 				&existing_vdev_mode,
1552 				&existing_chan_freq,
1553 				&existing_ch_width);
1554 		p2p_debug("Existing vdev_id %d, chan_freq %d and ch_width %d",
1555 			  existing_vdev_id, existing_chan_freq,
1556 			  existing_ch_width);
1557 		if (existing_vdev_id == WLAN_UMAC_VDEV_ID_MAX) {
1558 			p2p_debug("force scc not required");
1559 			return QDF_STATUS_SUCCESS;
1560 		}
1561 		if (existing_vdev_mode == PM_P2P_GO_MODE) {
1562 			policy_mgr_process_forcescc_for_go(psoc,
1563 							   existing_vdev_id,
1564 							   chan_freq,
1565 							   ch_width,
1566 							   PM_P2P_GO_MODE);
1567 			p2p_debug("CSA for vdev_id %d", existing_vdev_id);
1568 		}
1569 	}
1570 	return QDF_STATUS_SUCCESS;
1571 }
1572 #endif
1573