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