1 /*
2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19 /**
20 * DOC: Public APIs to perform operations on Peer object
21 */
22 #include <wlan_objmgr_cmn.h>
23 #include <wlan_objmgr_global_obj.h>
24 #include <wlan_objmgr_psoc_obj.h>
25 #include <wlan_objmgr_pdev_obj.h>
26 #include <wlan_objmgr_vdev_obj.h>
27 #include <wlan_objmgr_peer_obj.h>
28 #include <wlan_objmgr_debug.h>
29 #include <qdf_mem.h>
30 #include <qdf_module.h>
31 #include "wlan_objmgr_global_obj_i.h"
32 #include "wlan_objmgr_psoc_obj_i.h"
33 #include "wlan_objmgr_pdev_obj_i.h"
34 #include "wlan_objmgr_vdev_obj_i.h"
35
36
37 /*
38 * APIs to Create/Delete Peer object APIs
39 */
wlan_objmgr_peer_object_status(struct wlan_objmgr_peer * peer)40 static QDF_STATUS wlan_objmgr_peer_object_status(
41 struct wlan_objmgr_peer *peer)
42 {
43 uint8_t id;
44 QDF_STATUS status = QDF_STATUS_SUCCESS;
45
46 wlan_peer_obj_lock(peer);
47 /* Iterate through all components to derive the object status */
48 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
49 /* If component disabled, Ignore */
50 if (peer->obj_status[id] == QDF_STATUS_COMP_DISABLED)
51 continue;
52 /* If component operates in Async, status is Partially created,
53 break */
54 else if (peer->obj_status[id] == QDF_STATUS_COMP_ASYNC) {
55 if (!peer->peer_comp_priv_obj[id]) {
56 status = QDF_STATUS_COMP_ASYNC;
57 break;
58 }
59 /* If component failed to allocate its object, treat it as
60 failure, complete object need to be cleaned up */
61 } else if ((peer->obj_status[id] == QDF_STATUS_E_NOMEM) ||
62 (peer->obj_status[id] == QDF_STATUS_E_FAILURE)) {
63 obj_mgr_err("Peer comp object(id:%d) alloc fail", id);
64 status = QDF_STATUS_E_FAILURE;
65 break;
66 }
67 }
68 wlan_peer_obj_unlock(peer);
69 return status;
70 }
71
wlan_objmgr_peer_obj_free(struct wlan_objmgr_peer * peer)72 static QDF_STATUS wlan_objmgr_peer_obj_free(struct wlan_objmgr_peer *peer)
73 {
74 struct wlan_objmgr_psoc *psoc;
75 struct wlan_objmgr_vdev *vdev;
76 uint8_t *macaddr;
77 uint8_t vdev_id;
78 bool peer_free_notify = true;
79
80 if (!peer) {
81 obj_mgr_err("PEER is NULL");
82 return QDF_STATUS_E_FAILURE;
83 }
84
85 macaddr = wlan_peer_get_macaddr(peer);
86
87 vdev = wlan_peer_get_vdev(peer);
88 if (!vdev) {
89 obj_mgr_err(
90 "VDEV is NULL for peer("QDF_MAC_ADDR_FMT")",
91 QDF_MAC_ADDR_REF(macaddr));
92 return QDF_STATUS_E_FAILURE;
93 }
94
95 /* Notify peer free only for non self peer*/
96 if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer),
97 wlan_vdev_mlme_get_macaddr(vdev)) ==
98 QDF_STATUS_SUCCESS)
99 peer_free_notify = false;
100
101 vdev_id = wlan_vdev_get_id(vdev);
102
103 /* get PSOC from VDEV, if it is NULL, return */
104 psoc = wlan_vdev_get_psoc(vdev);
105 if (!psoc) {
106 obj_mgr_err(
107 "PSOC is NULL for peer("QDF_MAC_ADDR_FMT")",
108 QDF_MAC_ADDR_REF(macaddr));
109 return QDF_STATUS_E_FAILURE;
110 }
111
112 /* Decrement ref count for BSS peer, so that BSS peer deletes last*/
113 if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_STA) ||
114 (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA_TEMP) ||
115 (wlan_peer_get_peer_type(peer) == WLAN_PEER_P2P_CLI))
116 wlan_objmgr_peer_release_ref(wlan_vdev_get_bsspeer(vdev),
117 WLAN_OBJMGR_ID);
118
119 wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID);
120
121 /* Detach peer from VDEV's peer list */
122 if (wlan_objmgr_vdev_peer_detach(vdev, peer) == QDF_STATUS_E_FAILURE) {
123 obj_mgr_err(
124 "Peer("QDF_MAC_ADDR_FMT") VDEV detach fail, vdev id: %d",
125 QDF_MAC_ADDR_REF(macaddr), vdev_id);
126 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
127 return QDF_STATUS_E_FAILURE;
128 }
129 /* Detach peer from PSOC's peer list */
130 if (wlan_objmgr_psoc_peer_detach(psoc, peer) == QDF_STATUS_E_FAILURE) {
131 obj_mgr_err(
132 "Peer("QDF_MAC_ADDR_FMT") PSOC detach failure",
133 QDF_MAC_ADDR_REF(macaddr));
134 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
135 return QDF_STATUS_E_FAILURE;
136 }
137 wlan_objmgr_peer_trace_del_ref_list(peer);
138 wlan_objmgr_peer_trace_deinit_lock(peer);
139 qdf_spinlock_destroy(&peer->peer_lock);
140 qdf_mem_free(peer);
141 peer = NULL;
142
143 if (peer_free_notify)
144 wlan_objmgr_vdev_peer_freed_notify(vdev);
145
146 wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID);
147
148 return QDF_STATUS_SUCCESS;
149
150 }
151
152 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
153 static void
wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer * peer)154 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer *peer)
155 {
156 uint8_t id;
157
158 for (id = 0; id < WLAN_REF_ID_MAX; id++)
159 qdf_atomic_init(&peer->peer_objmgr.ref_id_dbg[id]);
160 }
161 #else
162 static inline void
wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer * peer)163 wlan_objmgr_peer_init_ref_id_debug(struct wlan_objmgr_peer *peer) {}
164 #endif
165
wlan_objmgr_peer_obj_create(struct wlan_objmgr_vdev * vdev,enum wlan_peer_type type,uint8_t * macaddr)166 struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create(
167 struct wlan_objmgr_vdev *vdev,
168 enum wlan_peer_type type,
169 uint8_t *macaddr)
170 {
171 struct wlan_objmgr_peer *peer;
172 struct wlan_objmgr_psoc *psoc;
173 wlan_objmgr_peer_create_handler handler;
174 wlan_objmgr_peer_status_handler stat_handler;
175 void *arg;
176 QDF_STATUS obj_status;
177 uint8_t id;
178
179 if (!vdev) {
180 obj_mgr_err(
181 "VDEV is NULL for peer ("QDF_MAC_ADDR_FMT")",
182 QDF_MAC_ADDR_REF(macaddr));
183 return NULL;
184 }
185 /* Get psoc, if psoc is NULL, return */
186 psoc = wlan_vdev_get_psoc(vdev);
187 if (!psoc) {
188 obj_mgr_err(
189 "PSOC is NULL for peer ("QDF_MAC_ADDR_FMT")",
190 QDF_MAC_ADDR_REF(macaddr));
191 return NULL;
192 }
193 /* Allocate memory for peer object */
194 peer = qdf_mem_malloc(sizeof(*peer));
195 if (!peer)
196 return NULL;
197
198 peer->obj_state = WLAN_OBJ_STATE_ALLOCATED;
199 qdf_atomic_init(&peer->peer_objmgr.ref_cnt);
200 wlan_objmgr_peer_init_ref_id_debug(peer);
201 wlan_objmgr_peer_trace_init_lock(peer);
202 wlan_objmgr_peer_get_ref(peer, WLAN_OBJMGR_ID);
203 /* set vdev to peer */
204 wlan_peer_set_vdev(peer, vdev);
205 /* set peer type */
206 wlan_peer_set_peer_type(peer, type);
207 /* set mac address of peer */
208 wlan_peer_set_macaddr(peer, macaddr);
209 /* initialize peer state */
210 wlan_peer_mlme_set_state(peer, WLAN_INIT_STATE);
211 wlan_peer_mlme_reset_seq_num(peer);
212 peer->peer_objmgr.print_cnt = 0;
213
214 qdf_spinlock_create(&peer->peer_lock);
215 /* Attach peer to psoc, psoc maintains the node table for the device */
216 if (wlan_objmgr_psoc_peer_attach(psoc, peer) !=
217 QDF_STATUS_SUCCESS) {
218 obj_mgr_warn(
219 "Peer("QDF_MAC_ADDR_FMT") PSOC attach failure",
220 QDF_MAC_ADDR_REF(macaddr));
221 qdf_spinlock_destroy(&peer->peer_lock);
222 wlan_objmgr_peer_trace_deinit_lock(peer);
223 qdf_mem_free(peer);
224 return NULL;
225 }
226 /* Attach peer to vdev peer table */
227 if (wlan_objmgr_vdev_peer_attach(vdev, peer) !=
228 QDF_STATUS_SUCCESS) {
229 obj_mgr_warn(
230 "Peer("QDF_MAC_ADDR_FMT") VDEV attach failure",
231 QDF_MAC_ADDR_REF(macaddr));
232 /* if attach fails, detach from psoc table before free */
233 wlan_objmgr_psoc_peer_detach(psoc, peer);
234 qdf_spinlock_destroy(&peer->peer_lock);
235 wlan_objmgr_peer_trace_deinit_lock(peer);
236 qdf_mem_free(peer);
237 return NULL;
238 }
239 wlan_peer_set_pdev_id(peer, wlan_objmgr_pdev_get_pdev_id(
240 wlan_vdev_get_pdev(vdev)));
241 /* Increment ref count for BSS peer, so that BSS peer deletes last*/
242 if ((type == WLAN_PEER_STA) || (type == WLAN_PEER_STA_TEMP)
243 || (type == WLAN_PEER_P2P_CLI))
244 wlan_objmgr_peer_get_ref(wlan_vdev_get_bsspeer(vdev),
245 WLAN_OBJMGR_ID);
246 /* TODO init other parameters */
247 /* Invoke registered create handlers */
248 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
249 handler = g_umac_glb_obj->peer_create_handler[id];
250 arg = g_umac_glb_obj->peer_create_handler_arg[id];
251 if (handler)
252 peer->obj_status[id] = handler(peer, arg);
253 else
254 peer->obj_status[id] = QDF_STATUS_COMP_DISABLED;
255 }
256 /* derive the object status */
257 obj_status = wlan_objmgr_peer_object_status(peer);
258 /* If SUCCESS, Object is created */
259 if (obj_status == QDF_STATUS_SUCCESS) {
260 peer->obj_state = WLAN_OBJ_STATE_CREATED;
261 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
262 stat_handler = g_umac_glb_obj->peer_status_handler[id];
263 arg = g_umac_glb_obj->peer_status_handler_arg[id];
264 if (stat_handler)
265 stat_handler(peer, arg,
266 QDF_STATUS_SUCCESS);
267 }
268 } else if (obj_status == QDF_STATUS_COMP_ASYNC) {
269 /* If any component operates in different context, update it
270 as partially created */
271 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
272 } else if (obj_status == QDF_STATUS_E_FAILURE) {
273 /* Clean up the peer */
274 obj_mgr_err(
275 "Peer("QDF_MAC_ADDR_FMT") comp object alloc fail",
276 QDF_MAC_ADDR_REF(macaddr));
277 wlan_objmgr_peer_obj_delete(peer);
278 return NULL;
279 }
280
281 obj_mgr_debug("Created peer " QDF_MAC_ADDR_FMT " type %d",
282 QDF_MAC_ADDR_REF(macaddr), type);
283
284 return peer;
285 }
286
287 static QDF_STATUS
__wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer * peer)288 __wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer)
289 {
290 uint8_t id;
291 wlan_objmgr_peer_destroy_handler handler;
292 QDF_STATUS obj_status;
293 void *arg;
294 uint8_t *macaddr;
295
296 if (!peer) {
297 obj_mgr_err("PEER is NULL");
298 return QDF_STATUS_E_FAILURE;
299 }
300 wlan_objmgr_notify_destroy(peer, WLAN_PEER_OP);
301
302 macaddr = wlan_peer_get_macaddr(peer);
303
304 obj_mgr_debug("Physically deleting peer " QDF_MAC_ADDR_FMT,
305 QDF_MAC_ADDR_REF(macaddr));
306
307 if (peer->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
308 obj_mgr_err("PEER object del is not invoked obj_state:%d peer "
309 QDF_MAC_ADDR_FMT, peer->obj_state,
310 QDF_MAC_ADDR_REF(macaddr));
311 WLAN_OBJMGR_BUG(0);
312 }
313
314 /* Invoke registered destroy handlers */
315 for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) {
316 handler = g_umac_glb_obj->peer_destroy_handler[id];
317 arg = g_umac_glb_obj->peer_destroy_handler_arg[id];
318 if (handler &&
319 (peer->obj_status[id] == QDF_STATUS_SUCCESS ||
320 peer->obj_status[id] == QDF_STATUS_COMP_ASYNC))
321 peer->obj_status[id] = handler(peer, arg);
322 else
323 peer->obj_status[id] = QDF_STATUS_COMP_DISABLED;
324 }
325 /* Derive the object status */
326 obj_status = wlan_objmgr_peer_object_status(peer);
327 if (obj_status == QDF_STATUS_E_FAILURE) {
328 /* If it status is failure, memory will not be freed */
329 QDF_BUG(0);
330 return QDF_STATUS_E_FAILURE;
331 }
332 /* few components deletion is in progress */
333 if (obj_status == QDF_STATUS_COMP_ASYNC) {
334 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED;
335 return QDF_STATUS_COMP_ASYNC;
336 }
337
338 /* Free the peer object */
339 return wlan_objmgr_peer_obj_free(peer);
340 }
341
342 #ifdef FEATURE_DELAYED_PEER_OBJ_DESTROY
343 /*
344 * Length of the list used to hold delayed peer obj free.
345 * Must be a multiple of 2.
346 */
347 #define MAX_DELAYED_FREE_PEERS 64
348
349 /**
350 * wlan_objmgr_peer_obj_free_work() - Peer obj freed in the delayed work
351 * @data: PDEV object
352 *
353 * Peer obj freed in the delayed work
354 *
355 * Return: None
356 */
wlan_objmgr_peer_obj_free_work(void * data)357 static void wlan_objmgr_peer_obj_free_work(void *data)
358 {
359 struct wlan_objmgr_pdev *pdev = data;
360 struct wlan_objmgr_peer *peer;
361 qdf_list_node_t *node;
362 uint8_t *macaddr;
363
364 if (!pdev) {
365 obj_mgr_err("pdev is NULL");
366 return;
367 }
368
369 qdf_spin_lock_bh(&pdev->peer_free_lock);
370 while (!(qdf_list_empty(&pdev->peer_free_list))) {
371 qdf_list_remove_front(&pdev->peer_free_list, &node);
372 qdf_spin_unlock_bh(&pdev->peer_free_lock);
373
374 peer = qdf_container_of(node,
375 struct wlan_objmgr_peer,
376 free_node);
377
378 macaddr = wlan_peer_get_macaddr(peer);
379 obj_mgr_debug("active_work_cnt %u list size %u peer 0x%pK("
380 QDF_MAC_ADDR_FMT ")",
381 pdev->active_work_cnt,
382 qdf_list_size(&pdev->peer_free_list),
383 peer,
384 QDF_MAC_ADDR_REF(macaddr));
385
386 __wlan_objmgr_peer_obj_destroy(peer);
387
388 qdf_spin_lock_bh(&pdev->peer_free_lock);
389 }
390
391 pdev->active_work_cnt--;
392
393 qdf_spin_unlock_bh(&pdev->peer_free_lock);
394 }
395
396 /**
397 * wlan_peer_obj_free_enqueue() - enqueue freed peer into kworker
398 * @peer: PEER object
399 *
400 * Enqueue freed peer into kworker
401 *
402 * Return: None
403 */
404 static QDF_STATUS
wlan_peer_obj_free_enqueue(struct wlan_objmgr_peer * peer)405 wlan_peer_obj_free_enqueue(struct wlan_objmgr_peer *peer)
406 {
407 struct wlan_objmgr_vdev *vdev;
408 struct wlan_objmgr_pdev *pdev;
409 uint8_t *macaddr;
410
411 if (!peer) {
412 obj_mgr_err("peer is NULL");
413 return QDF_STATUS_E_FAILURE;
414 }
415
416 macaddr = wlan_peer_get_macaddr(peer);
417
418 vdev = wlan_peer_get_vdev(peer);
419 if (!vdev) {
420 obj_mgr_err("VDEV is NULL for peer(" QDF_MAC_ADDR_FMT ")",
421 QDF_MAC_ADDR_REF(macaddr));
422 return QDF_STATUS_E_FAILURE;
423 }
424 /* get PDEV from VDEV, if it is NULL, return */
425 pdev = wlan_vdev_get_pdev(vdev);
426 if (!pdev) {
427 obj_mgr_err("PDEV is NULL for peer(" QDF_MAC_ADDR_FMT ")",
428 QDF_MAC_ADDR_REF(macaddr));
429 return QDF_STATUS_E_FAILURE;
430 }
431
432 qdf_spin_lock_bh(&pdev->peer_free_lock);
433 qdf_list_insert_back(&pdev->peer_free_list, &peer->free_node);
434 pdev->active_work_cnt++;
435 qdf_spin_unlock_bh(&pdev->peer_free_lock);
436
437 obj_mgr_debug("active_work_cnt %u list size %u peer 0x%pK("
438 QDF_MAC_ADDR_FMT ")",
439 pdev->active_work_cnt,
440 qdf_list_size(&pdev->peer_free_list),
441 peer,
442 QDF_MAC_ADDR_REF(macaddr));
443
444 qdf_sched_work(0, &pdev->peer_obj_free_work);
445
446 return QDF_STATUS_SUCCESS;
447 }
448
449 static QDF_STATUS
wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer * peer)450 wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer)
451 {
452 QDF_STATUS status;
453
454 if (qdf_in_atomic()) {
455 status = wlan_peer_obj_free_enqueue(peer);
456 if (status == QDF_STATUS_SUCCESS)
457 return status;
458
459 obj_mgr_err("enqueue failure, call free obj directly");
460 }
461
462 status = __wlan_objmgr_peer_obj_destroy(peer);
463
464 return status;
465 }
466
467 /**
468 * wlan_delayed_peer_obj_free_init() - Init for delayed peer obj freed queue
469 * @data: PDEV object
470 *
471 * Initialize main data structures to process peer obj destroy in a delayed
472 * workqueue.
473 *
474 * Return: QDF_STATUS_SUCCESS on success else a QDF error.
475 */
wlan_delayed_peer_obj_free_init(void * data)476 QDF_STATUS wlan_delayed_peer_obj_free_init(void *data)
477 {
478 struct wlan_objmgr_pdev *pdev = data;
479
480 if (!pdev) {
481 obj_mgr_err("pdev is NULL");
482 return QDF_STATUS_E_FAILURE;
483 }
484
485 qdf_spinlock_create(&pdev->peer_free_lock);
486 qdf_create_work(0, &pdev->peer_obj_free_work,
487 wlan_objmgr_peer_obj_free_work,
488 (void *)pdev);
489 pdev->active_work_cnt = 0;
490
491 /* Initialize PDEV's peer free list, assign default values */
492 qdf_list_create(&pdev->peer_free_list, MAX_DELAYED_FREE_PEERS);
493
494 obj_mgr_debug("Delayed peer obj free init successfully");
495
496 return QDF_STATUS_SUCCESS;
497 }
498
499 /**
500 * wlan_delayed_peer_obj_free_deinit() - De-Init delayed peer freed processing
501 * @data: PDEV object
502 *
503 * De-initialize main data structures to process peer obj freed in a delayed
504 * workqueue.
505 *
506 * Return: QDF_STATUS_SUCCESS on success else a QDF error.
507 */
wlan_delayed_peer_obj_free_deinit(void * data)508 QDF_STATUS wlan_delayed_peer_obj_free_deinit(void *data)
509 {
510 struct wlan_objmgr_pdev *pdev = data;
511
512 if (!pdev) {
513 obj_mgr_err("pdev is NULL");
514 return QDF_STATUS_E_FAILURE;
515 }
516
517 qdf_destroy_work(0, &pdev->peer_obj_free_work);
518 qdf_spinlock_destroy(&pdev->peer_free_lock);
519
520 obj_mgr_debug("Deinit successfully, active_work_cnt=%u",
521 pdev->active_work_cnt);
522
523 return QDF_STATUS_SUCCESS;
524 }
525 #else
526 static QDF_STATUS
wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer * peer)527 wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer)
528 {
529 return __wlan_objmgr_peer_obj_destroy(peer);
530 }
531 #endif
532
wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer * peer)533 QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer)
534 {
535 uint8_t print_idx;
536 uint8_t *macaddr;
537
538 if (!peer) {
539 obj_mgr_err("PEER is NULL");
540 return QDF_STATUS_E_FAILURE;
541 }
542
543 wlan_peer_obj_lock(peer);
544 macaddr = wlan_peer_get_macaddr(peer);
545 wlan_peer_obj_unlock(peer);
546
547 obj_mgr_debug("Logically deleting peer " QDF_MAC_ADDR_FMT,
548 QDF_MAC_ADDR_REF(macaddr));
549
550 print_idx = qdf_get_pidx();
551 wlan_objmgr_print_peer_ref_ids(peer, QDF_TRACE_LEVEL_DEBUG);
552 /*
553 * Update VDEV object state to LOGICALLY DELETED
554 * It prevents further access of this object
555 */
556 wlan_peer_obj_lock(peer);
557 peer->obj_state = WLAN_OBJ_STATE_LOGICALLY_DELETED;
558 wlan_peer_obj_unlock(peer);
559 wlan_objmgr_notify_log_delete(peer, WLAN_PEER_OP);
560 wlan_objmgr_peer_release_ref(peer, WLAN_OBJMGR_ID);
561
562 return QDF_STATUS_SUCCESS;
563 }
564 qdf_export_symbol(wlan_objmgr_peer_obj_delete);
565 /*
566 * APIs to attach/detach component objects
567 */
wlan_objmgr_peer_component_obj_attach(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id,void * comp_priv_obj,QDF_STATUS status)568 QDF_STATUS wlan_objmgr_peer_component_obj_attach(
569 struct wlan_objmgr_peer *peer,
570 enum wlan_umac_comp_id id,
571 void *comp_priv_obj,
572 QDF_STATUS status)
573 {
574 wlan_objmgr_peer_status_handler s_hler;
575 void *arg;
576 uint8_t i;
577 QDF_STATUS obj_status;
578
579 /* component id is invalid */
580 if (id >= WLAN_UMAC_MAX_COMPONENTS)
581 return QDF_STATUS_MAXCOMP_FAIL;
582
583 wlan_peer_obj_lock(peer);
584 /* If there is a valid entry, return failure,
585 valid object needs to be freed first */
586 if (peer->peer_comp_priv_obj[id]) {
587 wlan_peer_obj_unlock(peer);
588 return QDF_STATUS_E_FAILURE;
589 }
590 /* Assign component object private pointer(can be NULL also), status */
591 peer->peer_comp_priv_obj[id] = comp_priv_obj;
592 peer->obj_status[id] = status;
593 wlan_peer_obj_unlock(peer);
594
595 if (peer->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED)
596 return QDF_STATUS_SUCCESS;
597
598 /* If PEER object status is partially created means, this API is
599 invoked with different context. this block should be executed for async
600 components only */
601 /* Derive status */
602 obj_status = wlan_objmgr_peer_object_status(peer);
603 /* STATUS_SUCCESS means, object is CREATED */
604 if (obj_status == QDF_STATUS_SUCCESS)
605 peer->obj_state = WLAN_OBJ_STATE_CREATED;
606 /* update state as CREATION failed, caller has to delete the
607 PEER object */
608 else if (obj_status == QDF_STATUS_E_FAILURE)
609 peer->obj_state = WLAN_OBJ_STATE_CREATION_FAILED;
610 /* Notify components about the CREATION success/failure */
611 if ((obj_status == QDF_STATUS_SUCCESS) ||
612 (obj_status == QDF_STATUS_E_FAILURE)) {
613 /* notify object status */
614 for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
615 s_hler = g_umac_glb_obj->peer_status_handler[i];
616 arg = g_umac_glb_obj->peer_status_handler_arg[i];
617 if (s_hler)
618 s_hler(peer, arg, obj_status);
619 }
620 }
621 return QDF_STATUS_SUCCESS;
622 }
623
624 qdf_export_symbol(wlan_objmgr_peer_component_obj_attach);
625
wlan_objmgr_peer_component_obj_detach(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id,void * comp_priv_obj)626 QDF_STATUS wlan_objmgr_peer_component_obj_detach(
627 struct wlan_objmgr_peer *peer,
628 enum wlan_umac_comp_id id,
629 void *comp_priv_obj)
630 {
631 QDF_STATUS obj_status;
632
633 /* component id is invalid */
634 if (id >= WLAN_UMAC_MAX_COMPONENTS)
635 return QDF_STATUS_MAXCOMP_FAIL;
636
637 wlan_peer_obj_lock(peer);
638 /* If there is a invalid entry, return failure */
639 if (peer->peer_comp_priv_obj[id] != comp_priv_obj) {
640 peer->obj_status[id] = QDF_STATUS_E_FAILURE;
641 wlan_peer_obj_unlock(peer);
642 return QDF_STATUS_E_FAILURE;
643 }
644 /* Reset the pointer to NULL */
645 peer->peer_comp_priv_obj[id] = NULL;
646 peer->obj_status[id] = QDF_STATUS_SUCCESS;
647 wlan_peer_obj_unlock(peer);
648
649 /* If PEER object status is partially destroyed means, this API is
650 invoked with different context, this block should be executed for async
651 components only */
652 if ((peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) ||
653 (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) {
654 /* Derive object status */
655 obj_status = wlan_objmgr_peer_object_status(peer);
656 if (obj_status == QDF_STATUS_SUCCESS) {
657 /*Update the status as Deleted, if full object
658 deletion is in progress */
659 if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
660 peer->obj_state = WLAN_OBJ_STATE_DELETED;
661 /* Move to creation state, since this component
662 deletion alone requested */
663 if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
664 peer->obj_state = WLAN_OBJ_STATE_CREATED;
665 /* Object status is failure */
666 } else if (obj_status == QDF_STATUS_E_FAILURE) {
667 /*Update the status as Deletion failed, if full object
668 deletion is in progress */
669 if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED)
670 peer->obj_state =
671 WLAN_OBJ_STATE_DELETION_FAILED;
672 /* Move to creation state, since this component
673 deletion alone requested (do not block other
674 components) */
675 if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)
676 peer->obj_state = WLAN_OBJ_STATE_CREATED;
677 }
678
679 /* Delete peer object */
680 if ((obj_status == QDF_STATUS_SUCCESS) &&
681 (peer->obj_state == WLAN_OBJ_STATE_DELETED)) {
682 /* Free the peer object */
683 return wlan_objmgr_peer_obj_free(peer);
684 }
685 }
686
687 return QDF_STATUS_SUCCESS;
688 }
689
690 qdf_export_symbol(wlan_objmgr_peer_component_obj_detach);
691
wlan_objmgr_trigger_peer_comp_priv_object_creation(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)692 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_creation(
693 struct wlan_objmgr_peer *peer,
694 enum wlan_umac_comp_id id)
695 {
696 wlan_objmgr_peer_create_handler handler;
697 void *arg;
698 QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
699
700 /* Component id is invalid */
701 if (id >= WLAN_UMAC_MAX_COMPONENTS)
702 return QDF_STATUS_MAXCOMP_FAIL;
703
704 wlan_peer_obj_lock(peer);
705 /* If component object is already created, delete old
706 component object, then invoke creation */
707 if (peer->peer_comp_priv_obj[id]) {
708 wlan_peer_obj_unlock(peer);
709 return QDF_STATUS_E_FAILURE;
710 }
711 wlan_peer_obj_unlock(peer);
712
713 /* Invoke registered create handlers */
714 handler = g_umac_glb_obj->peer_create_handler[id];
715 arg = g_umac_glb_obj->peer_create_handler_arg[id];
716 if (handler)
717 peer->obj_status[id] = handler(peer, arg);
718 else
719 return QDF_STATUS_E_FAILURE;
720
721 /* If object status is created, then only handle this object status */
722 if (peer->obj_state == WLAN_OBJ_STATE_CREATED) {
723 /* Derive object status */
724 obj_status = wlan_objmgr_peer_object_status(peer);
725 /* Move PDEV object state to Partially created state */
726 if (obj_status == QDF_STATUS_COMP_ASYNC) {
727 /*TODO atomic */
728 peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED;
729 }
730 }
731
732 return obj_status;
733 }
734
735
wlan_objmgr_trigger_peer_comp_priv_object_deletion(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)736 QDF_STATUS wlan_objmgr_trigger_peer_comp_priv_object_deletion(
737 struct wlan_objmgr_peer *peer,
738 enum wlan_umac_comp_id id)
739 {
740 wlan_objmgr_peer_destroy_handler handler;
741 void *arg;
742 QDF_STATUS obj_status = QDF_STATUS_SUCCESS;
743
744 /* component id is invalid */
745 if (id >= WLAN_UMAC_MAX_COMPONENTS)
746 return QDF_STATUS_MAXCOMP_FAIL;
747
748 wlan_peer_obj_lock(peer);
749 /* Component object was never created, invalid operation */
750 if (!peer->peer_comp_priv_obj[id]) {
751 wlan_peer_obj_unlock(peer);
752 return QDF_STATUS_E_FAILURE;
753 }
754
755 wlan_peer_obj_unlock(peer);
756
757 /* Invoke registered destroy handlers */
758 handler = g_umac_glb_obj->peer_destroy_handler[id];
759 arg = g_umac_glb_obj->peer_destroy_handler_arg[id];
760 if (handler)
761 peer->obj_status[id] = handler(peer, arg);
762 else
763 return QDF_STATUS_E_FAILURE;
764
765 /* If object status is created, then only handle this object status */
766 if (peer->obj_state == WLAN_OBJ_STATE_CREATED) {
767 obj_status = wlan_objmgr_peer_object_status(peer);
768 /* move object state to DEL progress */
769 if (obj_status == QDF_STATUS_COMP_ASYNC)
770 peer->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS;
771 }
772 return obj_status;
773 }
774
wlan_objmgr_peer_get_comp_private_obj(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)775 void *wlan_objmgr_peer_get_comp_private_obj(
776 struct wlan_objmgr_peer *peer,
777 enum wlan_umac_comp_id id)
778 {
779 void *comp_priv_obj;
780
781 /* component id is invalid */
782 if (id >= WLAN_UMAC_MAX_COMPONENTS) {
783 QDF_BUG(0);
784 return NULL;
785 }
786
787 if (!peer) {
788 QDF_BUG(0);
789 return NULL;
790 }
791
792 comp_priv_obj = peer->peer_comp_priv_obj[id];
793 return comp_priv_obj;
794 }
795 qdf_export_symbol(wlan_objmgr_peer_get_comp_private_obj);
796
797 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
798 static inline void
wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)799 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer,
800 wlan_objmgr_ref_dbgid id)
801 {
802 qdf_atomic_inc(&peer->peer_objmgr.ref_id_dbg[id]);
803 }
804 #else
805 static inline void
wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)806 wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer,
807 wlan_objmgr_ref_dbgid id) {}
808 #endif
809
810 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
811 static QDF_STATUS
wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)812 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer,
813 wlan_objmgr_ref_dbgid id)
814 {
815 if (!qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id])) {
816 uint8_t *macaddr;
817
818 macaddr = wlan_peer_get_macaddr(peer);
819 obj_mgr_err(
820 "peer("QDF_MAC_ADDR_FMT") ref was not taken by %d",
821 QDF_MAC_ADDR_REF(macaddr), id);
822 wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg,
823 QDF_TRACE_LEVEL_FATAL);
824 WLAN_OBJMGR_BUG(0);
825 return QDF_STATUS_E_FAILURE;
826 }
827
828 qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]);
829 return QDF_STATUS_SUCCESS;
830 }
831 #else
832 static QDF_STATUS
wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)833 wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer,
834 wlan_objmgr_ref_dbgid id)
835 {
836 return QDF_STATUS_SUCCESS;
837 }
838 #endif
839
840 #ifdef WLAN_OBJMGR_REF_ID_TRACE
841 static inline void
wlan_objmgr_peer_ref_trace(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)842 wlan_objmgr_peer_ref_trace(struct wlan_objmgr_peer *peer,
843 wlan_objmgr_ref_dbgid id,
844 const char *func, int line)
845 {
846 struct wlan_objmgr_trace *trace;
847
848 trace = &peer->peer_objmgr.trace;
849
850 if (func)
851 wlan_objmgr_trace_ref(&trace->references[id].head,
852 trace, func, line);
853 }
854
855 static inline void
wlan_objmgr_peer_deref_trace(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)856 wlan_objmgr_peer_deref_trace(struct wlan_objmgr_peer *peer,
857 wlan_objmgr_ref_dbgid id,
858 const char *func, int line)
859 {
860 struct wlan_objmgr_trace *trace;
861
862 trace = &peer->peer_objmgr.trace;
863 if (func)
864 wlan_objmgr_trace_ref(&trace->dereferences[id].head,
865 trace, func, line);
866 }
867 #endif
868
869 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_objmgr_peer_get_ref_debug(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)870 void wlan_objmgr_peer_get_ref_debug(struct wlan_objmgr_peer *peer,
871 wlan_objmgr_ref_dbgid id,
872 const char *func, int line)
873 {
874 if (!peer) {
875 obj_mgr_err("peer obj is NULL for %d", id);
876 QDF_ASSERT(0);
877 return;
878 }
879 /* Increment ref count */
880 qdf_atomic_inc(&peer->peer_objmgr.ref_cnt);
881 wlan_objmgr_peer_get_debug_id_ref(peer, id);
882
883 wlan_objmgr_peer_ref_trace(peer, id, func, line);
884 return;
885 }
886
887 qdf_export_symbol(wlan_objmgr_peer_get_ref_debug);
888 #else
wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)889 void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer,
890 wlan_objmgr_ref_dbgid id)
891 {
892 if (!peer) {
893 obj_mgr_err("peer obj is NULL for %d", id);
894 QDF_ASSERT(0);
895 return;
896 }
897 /* Increment ref count */
898 qdf_atomic_inc(&peer->peer_objmgr.ref_cnt);
899 wlan_objmgr_peer_get_debug_id_ref(peer, id);
900 }
901
902 qdf_export_symbol(wlan_objmgr_peer_get_ref);
903 #endif
904
905 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_objmgr_peer_try_get_ref_debug(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)906 QDF_STATUS wlan_objmgr_peer_try_get_ref_debug(struct wlan_objmgr_peer *peer,
907 wlan_objmgr_ref_dbgid id,
908 const char *func, int line)
909 {
910 if (!peer) {
911 obj_mgr_err("peer obj is NULL for %d", id);
912 QDF_ASSERT(0);
913 return QDF_STATUS_E_FAILURE;
914 }
915
916 wlan_peer_obj_lock(peer);
917 if (peer->obj_state != WLAN_OBJ_STATE_CREATED) {
918 wlan_peer_obj_unlock(peer);
919 if (peer->peer_objmgr.print_cnt++ <=
920 WLAN_OBJMGR_RATELIMIT_THRESH) {
921 uint8_t *macaddr;
922
923 macaddr = wlan_peer_get_macaddr(peer);
924 obj_mgr_debug(
925 "peer(" QDF_MAC_ADDR_FMT ") not in Created st(%d)",
926 QDF_MAC_ADDR_REF(macaddr),
927 peer->obj_state);
928 }
929 return QDF_STATUS_E_RESOURCES;
930 }
931
932 wlan_objmgr_peer_get_ref_debug(peer, id, func, line);
933 wlan_peer_obj_unlock(peer);
934
935 return QDF_STATUS_SUCCESS;
936 }
937
938 qdf_export_symbol(wlan_objmgr_peer_try_get_ref_debug);
939 #else
wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)940 QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer,
941 wlan_objmgr_ref_dbgid id)
942 {
943 if (!peer) {
944 obj_mgr_err("peer obj is NULL for %d", id);
945 QDF_ASSERT(0);
946 return QDF_STATUS_E_FAILURE;
947 }
948
949 wlan_peer_obj_lock(peer);
950 if (peer->obj_state != WLAN_OBJ_STATE_CREATED) {
951 wlan_peer_obj_unlock(peer);
952 if (peer->peer_objmgr.print_cnt++ <=
953 WLAN_OBJMGR_RATELIMIT_THRESH) {
954 uint8_t *macaddr;
955
956 macaddr = wlan_peer_get_macaddr(peer);
957 obj_mgr_debug(
958 "peer(" QDF_MAC_ADDR_FMT ") not in Created st(%d)",
959 QDF_MAC_ADDR_REF(macaddr),
960 peer->obj_state);
961 }
962 return QDF_STATUS_E_RESOURCES;
963 }
964
965 wlan_objmgr_peer_get_ref(peer, id);
966 wlan_peer_obj_unlock(peer);
967
968 return QDF_STATUS_SUCCESS;
969 }
970
971 qdf_export_symbol(wlan_objmgr_peer_try_get_ref);
972 #endif
973
974 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_peer_get_next_active_peer_of_psoc_debug(struct wlan_peer_list * peer_list,uint8_t hash_index,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)975 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc_debug(
976 struct wlan_peer_list *peer_list,
977 uint8_t hash_index,
978 struct wlan_objmgr_peer *peer,
979 wlan_objmgr_ref_dbgid dbg_id,
980 const char *func, int line)
981 {
982 struct wlan_objmgr_peer *peer_next = NULL;
983 qdf_list_node_t *psoc_node = NULL;
984 qdf_list_node_t *prev_psoc_node = NULL;
985 qdf_list_t *obj_list;
986
987 qdf_spin_lock_bh(&peer_list->peer_list_lock);
988 obj_list = &peer_list->peer_hash[hash_index];
989
990 prev_psoc_node = &peer->psoc_peer;
991 while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
992 QDF_STATUS_SUCCESS) {
993 peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
994 psoc_peer);
995
996 if (wlan_objmgr_peer_try_get_ref_debug(peer_next, dbg_id,
997 func, line) ==
998 QDF_STATUS_SUCCESS) {
999 qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1000 return peer_next;
1001 }
1002
1003 prev_psoc_node = psoc_node;
1004 }
1005
1006 qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1007
1008 return NULL;
1009 }
1010 #else
wlan_peer_get_next_active_peer_of_psoc(struct wlan_peer_list * peer_list,uint8_t hash_index,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id)1011 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc(
1012 struct wlan_peer_list *peer_list,
1013 uint8_t hash_index,
1014 struct wlan_objmgr_peer *peer,
1015 wlan_objmgr_ref_dbgid dbg_id)
1016 {
1017 struct wlan_objmgr_peer *peer_next = NULL;
1018 qdf_list_node_t *psoc_node = NULL;
1019 qdf_list_node_t *prev_psoc_node = NULL;
1020 qdf_list_t *obj_list;
1021
1022 qdf_spin_lock_bh(&peer_list->peer_list_lock);
1023 obj_list = &peer_list->peer_hash[hash_index];
1024
1025 prev_psoc_node = &peer->psoc_peer;
1026 while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
1027 QDF_STATUS_SUCCESS) {
1028 peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
1029 psoc_peer);
1030
1031 if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) ==
1032 QDF_STATUS_SUCCESS) {
1033 qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1034 return peer_next;
1035 }
1036
1037 prev_psoc_node = psoc_node;
1038 }
1039
1040 qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1041
1042 return NULL;
1043 }
1044 #endif
1045
1046 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_vdev_peer_list_peek_active_head_debug(struct wlan_objmgr_vdev * vdev,qdf_list_t * peer_list,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1047 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head_debug(
1048 struct wlan_objmgr_vdev *vdev,
1049 qdf_list_t *peer_list,
1050 wlan_objmgr_ref_dbgid dbg_id,
1051 const char *func, int line)
1052 {
1053 struct wlan_objmgr_peer *peer;
1054 qdf_list_node_t *vdev_node = NULL;
1055 qdf_list_node_t *prev_vdev_node = NULL;
1056
1057 wlan_vdev_obj_lock(vdev);
1058
1059 if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) {
1060 wlan_vdev_obj_unlock(vdev);
1061 return NULL;
1062 }
1063
1064 do {
1065 peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1066 vdev_peer);
1067
1068 if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id,
1069 func, line) ==
1070 QDF_STATUS_SUCCESS) {
1071 wlan_vdev_obj_unlock(vdev);
1072 return peer;
1073 }
1074
1075 prev_vdev_node = vdev_node;
1076 } while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1077 QDF_STATUS_SUCCESS);
1078
1079 wlan_vdev_obj_unlock(vdev);
1080
1081 return NULL;
1082 }
1083 #else
wlan_vdev_peer_list_peek_active_head(struct wlan_objmgr_vdev * vdev,qdf_list_t * peer_list,wlan_objmgr_ref_dbgid dbg_id)1084 struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head(
1085 struct wlan_objmgr_vdev *vdev,
1086 qdf_list_t *peer_list,
1087 wlan_objmgr_ref_dbgid dbg_id)
1088 {
1089 struct wlan_objmgr_peer *peer;
1090 qdf_list_node_t *vdev_node = NULL;
1091 qdf_list_node_t *prev_vdev_node = NULL;
1092
1093 wlan_vdev_obj_lock(vdev);
1094
1095 if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) {
1096 wlan_vdev_obj_unlock(vdev);
1097 return NULL;
1098 }
1099
1100 do {
1101 peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1102 vdev_peer);
1103
1104 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
1105 QDF_STATUS_SUCCESS) {
1106 wlan_vdev_obj_unlock(vdev);
1107 return peer;
1108 }
1109
1110 prev_vdev_node = vdev_node;
1111 } while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1112 QDF_STATUS_SUCCESS);
1113
1114 wlan_vdev_obj_unlock(vdev);
1115
1116 return NULL;
1117 }
1118 #endif
1119
1120 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_peer_get_next_active_peer_of_vdev_debug(struct wlan_objmgr_vdev * vdev,qdf_list_t * peer_list,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1121 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev_debug(
1122 struct wlan_objmgr_vdev *vdev,
1123 qdf_list_t *peer_list,
1124 struct wlan_objmgr_peer *peer,
1125 wlan_objmgr_ref_dbgid dbg_id,
1126 const char *func, int line)
1127 {
1128 struct wlan_objmgr_peer *peer_next;
1129 qdf_list_node_t *vdev_node = NULL;
1130 qdf_list_node_t *prev_vdev_node = NULL;
1131
1132 if (!peer)
1133 return NULL;
1134
1135 wlan_vdev_obj_lock(vdev);
1136
1137 prev_vdev_node = &peer->vdev_peer;
1138 while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1139 QDF_STATUS_SUCCESS) {
1140 peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1141 vdev_peer);
1142
1143 if (wlan_objmgr_peer_try_get_ref_debug(peer_next, dbg_id,
1144 func, line) ==
1145 QDF_STATUS_SUCCESS) {
1146 wlan_vdev_obj_unlock(vdev);
1147 return peer_next;
1148 }
1149
1150 prev_vdev_node = vdev_node;
1151 }
1152
1153 wlan_vdev_obj_unlock(vdev);
1154
1155 return NULL;
1156 }
1157 #else
wlan_peer_get_next_active_peer_of_vdev(struct wlan_objmgr_vdev * vdev,qdf_list_t * peer_list,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id)1158 struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev(
1159 struct wlan_objmgr_vdev *vdev,
1160 qdf_list_t *peer_list,
1161 struct wlan_objmgr_peer *peer,
1162 wlan_objmgr_ref_dbgid dbg_id)
1163 {
1164 struct wlan_objmgr_peer *peer_next;
1165 qdf_list_node_t *vdev_node = NULL;
1166 qdf_list_node_t *prev_vdev_node = NULL;
1167
1168 if (!peer)
1169 return NULL;
1170
1171 wlan_vdev_obj_lock(vdev);
1172
1173 prev_vdev_node = &peer->vdev_peer;
1174 while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) ==
1175 QDF_STATUS_SUCCESS) {
1176 peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer,
1177 vdev_peer);
1178
1179 if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) ==
1180 QDF_STATUS_SUCCESS) {
1181 wlan_vdev_obj_unlock(vdev);
1182 return peer_next;
1183 }
1184
1185 prev_vdev_node = vdev_node;
1186 }
1187
1188 wlan_vdev_obj_unlock(vdev);
1189
1190 return NULL;
1191 }
1192 #endif
1193
1194 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_psoc_peer_list_peek_active_head_debug(struct wlan_peer_list * peer_list,uint8_t hash_index,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1195 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head_debug(
1196 struct wlan_peer_list *peer_list,
1197 uint8_t hash_index,
1198 wlan_objmgr_ref_dbgid dbg_id,
1199 const char *func, int line)
1200 {
1201 struct wlan_objmgr_peer *peer;
1202 qdf_list_node_t *psoc_node = NULL;
1203 qdf_list_node_t *prev_psoc_node = NULL;
1204 qdf_list_t *obj_list;
1205
1206 qdf_spin_lock_bh(&peer_list->peer_list_lock);
1207 obj_list = &peer_list->peer_hash[hash_index];
1208
1209 if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) {
1210 qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1211 return NULL;
1212 }
1213
1214 do {
1215 peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
1216 psoc_peer);
1217 if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id,
1218 func, line) ==
1219 QDF_STATUS_SUCCESS) {
1220 qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1221 return peer;
1222 }
1223
1224 prev_psoc_node = psoc_node;
1225 } while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
1226 QDF_STATUS_SUCCESS);
1227
1228 qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1229 return NULL;
1230 }
1231 #else
wlan_psoc_peer_list_peek_active_head(struct wlan_peer_list * peer_list,uint8_t hash_index,wlan_objmgr_ref_dbgid dbg_id)1232 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head(
1233 struct wlan_peer_list *peer_list,
1234 uint8_t hash_index,
1235 wlan_objmgr_ref_dbgid dbg_id)
1236 {
1237 struct wlan_objmgr_peer *peer;
1238 qdf_list_node_t *psoc_node = NULL;
1239 qdf_list_node_t *prev_psoc_node = NULL;
1240 qdf_list_t *obj_list;
1241
1242 qdf_spin_lock_bh(&peer_list->peer_list_lock);
1243 obj_list = &peer_list->peer_hash[hash_index];
1244
1245 if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) {
1246 qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1247 return NULL;
1248 }
1249
1250 do {
1251 peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer,
1252 psoc_peer);
1253 if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) ==
1254 QDF_STATUS_SUCCESS) {
1255 qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1256 return peer;
1257 }
1258
1259 prev_psoc_node = psoc_node;
1260 } while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) ==
1261 QDF_STATUS_SUCCESS);
1262
1263 qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1264 return NULL;
1265 }
1266 #endif
1267
1268 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_psoc_peer_list_peek_head_ref_debug(struct wlan_peer_list * peer_list,uint8_t hash_index,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1269 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref_debug(
1270 struct wlan_peer_list *peer_list,
1271 uint8_t hash_index,
1272 wlan_objmgr_ref_dbgid dbg_id,
1273 const char *func, int line)
1274 {
1275 struct wlan_objmgr_peer *peer;
1276 qdf_list_t *obj_list;
1277
1278 qdf_spin_lock_bh(&peer_list->peer_list_lock);
1279 obj_list = &peer_list->peer_hash[hash_index];
1280
1281 peer = wlan_psoc_peer_list_peek_head(obj_list);
1282
1283 /* This API is invoked by caller, only when caller need to access the
1284 * peer object, though object is not in active state, this API should be
1285 * used carefully, where multiple object frees are not triggered
1286 */
1287 if (peer)
1288 wlan_objmgr_peer_get_ref_debug(peer, dbg_id, func, line);
1289
1290 qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1291
1292 return peer;
1293 }
1294 #else
wlan_psoc_peer_list_peek_head_ref(struct wlan_peer_list * peer_list,uint8_t hash_index,wlan_objmgr_ref_dbgid dbg_id)1295 struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref(
1296 struct wlan_peer_list *peer_list,
1297 uint8_t hash_index,
1298 wlan_objmgr_ref_dbgid dbg_id)
1299 {
1300 struct wlan_objmgr_peer *peer;
1301 qdf_list_t *obj_list;
1302
1303 qdf_spin_lock_bh(&peer_list->peer_list_lock);
1304 obj_list = &peer_list->peer_hash[hash_index];
1305
1306 peer = wlan_psoc_peer_list_peek_head(obj_list);
1307
1308 /* This API is invoked by caller, only when caller need to access the
1309 * peer object, though object is not in active state, this API should be
1310 * used carefully, where multiple object frees are not triggered
1311 */
1312 if (peer)
1313 wlan_objmgr_peer_get_ref(peer, dbg_id);
1314
1315 qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1316
1317 return peer;
1318 }
1319 #endif
1320
1321 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_peer_get_next_peer_of_psoc_ref_debug(struct wlan_peer_list * peer_list,uint8_t hash_index,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id,const char * func,int line)1322 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref_debug(
1323 struct wlan_peer_list *peer_list, uint8_t hash_index,
1324 struct wlan_objmgr_peer *peer,
1325 wlan_objmgr_ref_dbgid dbg_id,
1326 const char *func, int line)
1327 {
1328 qdf_list_t *obj_list;
1329 struct wlan_objmgr_peer *peer_next;
1330
1331 qdf_spin_lock_bh(&peer_list->peer_list_lock);
1332 obj_list = &peer_list->peer_hash[hash_index];
1333
1334 peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer);
1335 /* This API is invoked by caller, only when caller need to access the
1336 * peer object, though object is not in active state, this API should be
1337 * used carefully, where multiple free on object are not triggered
1338 */
1339 if (peer_next)
1340 wlan_objmgr_peer_get_ref_debug(peer_next, dbg_id, func, line);
1341
1342 qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1343
1344 return peer_next;
1345 }
1346 #else
wlan_peer_get_next_peer_of_psoc_ref(struct wlan_peer_list * peer_list,uint8_t hash_index,struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid dbg_id)1347 struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref(
1348 struct wlan_peer_list *peer_list, uint8_t hash_index,
1349 struct wlan_objmgr_peer *peer,
1350 wlan_objmgr_ref_dbgid dbg_id)
1351 {
1352 qdf_list_t *obj_list;
1353 struct wlan_objmgr_peer *peer_next;
1354
1355 qdf_spin_lock_bh(&peer_list->peer_list_lock);
1356 obj_list = &peer_list->peer_hash[hash_index];
1357
1358 peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer);
1359 /* This API is invoked by caller, only when caller need to access the
1360 * peer object, though object is not in active state, this API should be
1361 * used carefully, where multiple free on object are not triggered
1362 */
1363 if (peer_next)
1364 wlan_objmgr_peer_get_ref(peer_next, dbg_id);
1365
1366 qdf_spin_unlock_bh(&peer_list->peer_list_lock);
1367
1368 return peer_next;
1369 }
1370 #endif
1371
1372 #ifdef WLAN_OBJMGR_REF_ID_TRACE
wlan_objmgr_peer_release_ref_debug(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id,const char * func,int line)1373 void wlan_objmgr_peer_release_ref_debug(struct wlan_objmgr_peer *peer,
1374 wlan_objmgr_ref_dbgid id,
1375 const char *func, int line)
1376 {
1377 QDF_STATUS status;
1378
1379 if (!peer) {
1380 obj_mgr_err("peer obj is NULL for %d", id);
1381 QDF_ASSERT(0);
1382 return;
1383 }
1384
1385 if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
1386 uint8_t *macaddr;
1387
1388 macaddr = wlan_peer_get_macaddr(peer);
1389 obj_mgr_err("peer("QDF_MAC_ADDR_FMT") ref cnt is 0",
1390 QDF_MAC_ADDR_REF(macaddr));
1391 WLAN_OBJMGR_BUG(0);
1392 return;
1393 }
1394
1395 status = wlan_objmgr_peer_release_debug_id_ref(peer, id);
1396 if (QDF_IS_STATUS_ERROR(status))
1397 return;
1398
1399 wlan_objmgr_peer_deref_trace(peer, id, func, line);
1400 /* Provide synchronization from the access to add peer
1401 * to logically deleted peer list.
1402 */
1403 wlan_peer_obj_lock(peer);
1404 /* Decrement ref count, free peer object, if ref count == 0 */
1405 if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) {
1406 wlan_peer_obj_unlock(peer);
1407 wlan_objmgr_peer_obj_destroy(peer);
1408 } else {
1409 wlan_peer_obj_unlock(peer);
1410 }
1411
1412 return;
1413 }
1414
1415 qdf_export_symbol(wlan_objmgr_peer_release_ref_debug);
1416 #else
wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer * peer,wlan_objmgr_ref_dbgid id)1417 void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer,
1418 wlan_objmgr_ref_dbgid id)
1419 {
1420 QDF_STATUS status;
1421
1422 if (!peer) {
1423 obj_mgr_err("peer obj is NULL for %d", id);
1424 QDF_ASSERT(0);
1425 return;
1426 }
1427
1428 if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) {
1429 uint8_t *macaddr;
1430
1431 macaddr = wlan_peer_get_macaddr(peer);
1432 obj_mgr_err("peer("QDF_MAC_ADDR_FMT") ref cnt is 0",
1433 QDF_MAC_ADDR_REF(macaddr));
1434 WLAN_OBJMGR_BUG(0);
1435 return;
1436 }
1437
1438 status = wlan_objmgr_peer_release_debug_id_ref(peer, id);
1439 if (QDF_IS_STATUS_ERROR(status))
1440 return;
1441
1442 /* Provide synchronization from the access to add peer
1443 * to logically deleted peer list.
1444 */
1445 wlan_peer_obj_lock(peer);
1446 /* Decrement ref count, free peer object, if ref count == 0 */
1447 if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) {
1448 wlan_peer_obj_unlock(peer);
1449 wlan_objmgr_peer_obj_destroy(peer);
1450 } else {
1451 wlan_peer_obj_unlock(peer);
1452 }
1453 }
1454
1455 qdf_export_symbol(wlan_objmgr_peer_release_ref);
1456 #endif
1457
1458 #ifdef WLAN_OBJMGR_REF_ID_DEBUG
1459 void
wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer * peer,QDF_TRACE_LEVEL log_level)1460 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer,
1461 QDF_TRACE_LEVEL log_level)
1462 {
1463 wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, log_level);
1464 }
1465
1466 uint32_t
wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)1467 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer,
1468 enum wlan_umac_comp_id id)
1469 {
1470 return qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id]);
1471 }
1472 #else
1473 void
wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer * peer,QDF_TRACE_LEVEL log_level)1474 wlan_objmgr_print_peer_ref_ids(struct wlan_objmgr_peer *peer,
1475 QDF_TRACE_LEVEL log_level)
1476 {
1477 uint32_t pending_ref;
1478
1479 pending_ref = qdf_atomic_read(&peer->peer_objmgr.ref_cnt);
1480 obj_mgr_log_level(log_level, "Pending refs -- %d", pending_ref);
1481 }
1482
1483 uint32_t
wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer * peer,enum wlan_umac_comp_id id)1484 wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer,
1485 enum wlan_umac_comp_id id)
1486 {
1487 return 0;
1488 }
1489 #endif
1490
1491 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE
wlan_peer_update_macaddr(struct wlan_objmgr_peer * peer,uint8_t * new_macaddr)1492 QDF_STATUS wlan_peer_update_macaddr(struct wlan_objmgr_peer *peer,
1493 uint8_t *new_macaddr)
1494 {
1495 struct wlan_objmgr_psoc *psoc;
1496 struct wlan_objmgr_vdev *vdev;
1497 uint8_t *macaddr;
1498 QDF_STATUS status;
1499
1500 if (!peer) {
1501 obj_mgr_err("PEER is NULL");
1502 return QDF_STATUS_E_FAILURE;
1503 }
1504
1505 macaddr = wlan_peer_get_macaddr(peer);
1506
1507 vdev = wlan_peer_get_vdev(peer);
1508 if (!vdev) {
1509 obj_mgr_err("VDEV is NULL for peer(" QDF_MAC_ADDR_FMT ")",
1510 QDF_MAC_ADDR_REF(macaddr));
1511 return QDF_STATUS_E_FAILURE;
1512 }
1513
1514 /* get PSOC from VDEV, if it is NULL, return */
1515 psoc = wlan_vdev_get_psoc(vdev);
1516 if (!psoc) {
1517 obj_mgr_err("PSOC is NULL for peer(" QDF_MAC_ADDR_FMT ")",
1518 QDF_MAC_ADDR_REF(macaddr));
1519 return QDF_STATUS_E_FAILURE;
1520 }
1521
1522 status = wlan_objmgr_psoc_peer_detach(psoc, peer);
1523 if (QDF_IS_STATUS_ERROR(status)) {
1524 obj_mgr_err("Failed to detach peer(" QDF_MAC_ADDR_FMT ")",
1525 QDF_MAC_ADDR_REF(macaddr));
1526 return status;
1527 }
1528
1529 wlan_peer_set_macaddr(peer, new_macaddr);
1530
1531 status = wlan_objmgr_psoc_peer_attach(psoc, peer);
1532 if (QDF_IS_STATUS_ERROR(status)) {
1533 obj_mgr_err("Failed to attach peer(" QDF_MAC_ADDR_FMT ")",
1534 QDF_MAC_ADDR_REF(new_macaddr));
1535 return status;
1536 }
1537 return QDF_STATUS_SUCCESS;
1538 }
1539 #endif
1540