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