1  /*
2   * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
3   * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4   *
5   * Permission to use, copy, modify, and/or distribute this software for
6   * any purpose with or without fee is hereby granted, provided that the
7   * above copyright notice and this permission notice appear in all
8   * copies.
9   *
10   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11   * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12   * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13   * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14   * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15   * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16   * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17   * PERFORMANCE OF THIS SOFTWARE.
18   */
19  
20  /**
21   * DOC: This file contains various object manager related wrappers and helpers
22   */
23  
24  #ifndef _WLAN_PMO_OBJMGR_H
25  #define _WLAN_PMO_OBJMGR_H
26  
27  #ifdef WLAN_POWER_MANAGEMENT_OFFLOAD
28  
29  #include "wlan_cmn.h"
30  #include "wlan_objmgr_cmn.h"
31  #include "wlan_objmgr_peer_obj.h"
32  #include "wlan_objmgr_vdev_obj.h"
33  #include "wlan_objmgr_pdev_obj.h"
34  #include "wlan_objmgr_psoc_obj.h"
35  #include "wlan_pmo_obj_mgmt_public_struct.h"
36  #include "wlan_utility.h"
37  
38  
39  /* Get/Put Ref */
40  
41  #define pmo_peer_get_ref(peer) wlan_objmgr_peer_try_get_ref(peer, WLAN_PMO_ID)
42  #define pmo_peer_put_ref(peer) wlan_objmgr_peer_release_ref(peer, WLAN_PMO_ID)
43  
44  #define pmo_vdev_get_ref(vdev) wlan_objmgr_vdev_try_get_ref(vdev, WLAN_PMO_ID)
45  
46  #define pmo_pdev_get_ref(pdev) wlan_objmgr_pdev_try_get_ref(pdev, WLAN_PMO_ID)
47  #define pmo_pdev_put_ref(pdev) wlan_objmgr_pdev_release_ref(pdev, WLAN_PMO_ID)
48  
49  #define pmo_psoc_get_ref(psoc) wlan_objmgr_psoc_try_get_ref(psoc, WLAN_PMO_ID)
50  #define pmo_psoc_put_ref(psoc) wlan_objmgr_psoc_release_ref(psoc, WLAN_PMO_ID)
51  
52  /* Private Data */
53  
54  #define pmo_vdev_get_priv_nolock(vdev) \
55  	wlan_objmgr_vdev_get_comp_private_obj(vdev, WLAN_UMAC_COMP_PMO)
56  #define pmo_psoc_get_priv_nolock(psoc) \
57  	wlan_objmgr_psoc_get_comp_private_obj(psoc, WLAN_UMAC_COMP_PMO)
58  
59  /* Ids */
60  
61  static inline uint8_t
pmo_vdev_get_id(struct wlan_objmgr_vdev * vdev)62  pmo_vdev_get_id(struct wlan_objmgr_vdev *vdev)
63  {
64  	uint8_t vdev_id;
65  
66  	vdev_id = wlan_vdev_get_id(vdev);
67  	QDF_BUG(vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS);
68  
69  	return vdev_id;
70  }
71  
72  /* Tree Navigation */
73  
74  /*
75   * !PLEASE READ!
76   *
77   * The following are objmgr naviation helpers for traversing objmgr object
78   * trees.
79   *
80   * Objmgr ensures parents of an objmgr object cannot be freed while a valid
81   * reference to one of its children is held. Based on this fact, all of these
82   * navigation helpers make the following assumptions to ensure safe usage:
83   *
84   * 1) The caller must hold a valid reference to the input objmgr object!
85   *	E.g. Use pmo_[peer|vdev|pdev|psoc]_get_ref() on the input objmgr object
86   *	before using these APIs
87   * 2) Given assumption #1, the caller does not need to hold a reference to the
88   *	parents of the input objmgr object
89   * 3) Given assumption #1, parents of the input objmgr object cannot be null
90   * 4) Given assumption #1, private contexts of any parent of the input objmgr
91   *	object cannot be null
92   *
93   * These characteristics remove the need for most sanity checks when dealing
94   * with objmgr objects. However, please note that if you ever walk the tree
95   * from parent to child, references must be acquired all the way down!
96   *
97   * Example #1:
98   *
99   *	psoc = pmo_vdev_get_psoc(vdev);
100   *	if (!psoc)
101   *		// this is dead code
102   *
103   * Example #2:
104   *
105   *	psoc_priv = pmo_psoc_get_priv(psoc);
106   *	if (!psoci_priv)
107   *		// this is dead code
108   *
109   * Example #3:
110   *
111   *	status = pmo_vdev_get_ref(vdev);
112   *
113   *	...
114   *
115   *	psoc = pmo_vdev_get_psoc(vdev);
116   *
117   *	// the next line is redundant, don't do it!
118   *	status = pmo_psoc_get_ref(psoc);
119   */
120  
121  /* Tree Navigation: psoc */
122  
123  static inline struct pmo_psoc_priv_obj *
pmo_psoc_get_priv(struct wlan_objmgr_psoc * psoc)124  pmo_psoc_get_priv(struct wlan_objmgr_psoc *psoc)
125  {
126  	struct pmo_psoc_priv_obj *psoc_priv;
127  
128  	psoc_priv = pmo_psoc_get_priv_nolock(psoc);
129  	QDF_BUG(psoc_priv);
130  
131  	return psoc_priv;
132  }
133  
__pmo_spinlock_bh_safe(struct pmo_psoc_priv_obj * psoc_ctx)134  static inline bool __pmo_spinlock_bh_safe(struct pmo_psoc_priv_obj *psoc_ctx)
135  {
136  	if (!psoc_ctx)
137  		return false;
138  
139  	qdf_spin_lock_bh(&psoc_ctx->lock);
140  
141  	return true;
142  }
143  
144  #define pmo_psoc_with_ctx(psoc, cursor) \
145  	for (cursor = pmo_psoc_get_priv(psoc); \
146  	     __pmo_spinlock_bh_safe(cursor); \
147  	     qdf_spin_unlock_bh(&cursor->lock), cursor = NULL)
148  
149  /* Tree Navigation: pdev */
150  
151  static inline struct wlan_objmgr_psoc *
pmo_pdev_get_psoc(struct wlan_objmgr_pdev * pdev)152  pmo_pdev_get_psoc(struct wlan_objmgr_pdev *pdev)
153  {
154  	struct wlan_objmgr_psoc *psoc;
155  
156  	psoc = wlan_pdev_get_psoc(pdev);
157  	QDF_BUG(psoc);
158  
159  	return psoc;
160  }
161  
162  static inline struct pmo_psoc_priv_obj *
pmo_pdev_get_psoc_priv(struct wlan_objmgr_pdev * pdev)163  pmo_pdev_get_psoc_priv(struct wlan_objmgr_pdev *pdev)
164  {
165  	return pmo_psoc_get_priv(pmo_pdev_get_psoc(pdev));
166  }
167  
168  /* Tree Navigation: vdev */
169  
170  static inline struct pmo_vdev_priv_obj *
pmo_vdev_get_priv(struct wlan_objmgr_vdev * vdev)171  pmo_vdev_get_priv(struct wlan_objmgr_vdev *vdev)
172  {
173  	struct pmo_vdev_priv_obj *vdev_priv;
174  
175  	vdev_priv = pmo_vdev_get_priv_nolock(vdev);
176  	QDF_BUG(vdev_priv);
177  
178  	return vdev_priv;
179  }
180  
181  static inline struct wlan_objmgr_pdev *
pmo_vdev_get_pdev(struct wlan_objmgr_vdev * vdev)182  pmo_vdev_get_pdev(struct wlan_objmgr_vdev *vdev)
183  {
184  	struct wlan_objmgr_pdev *pdev;
185  
186  	pdev = wlan_vdev_get_pdev(vdev);
187  	QDF_BUG(pdev);
188  
189  	return pdev;
190  }
191  
192  static inline struct wlan_objmgr_psoc *
pmo_vdev_get_psoc(struct wlan_objmgr_vdev * vdev)193  pmo_vdev_get_psoc(struct wlan_objmgr_vdev *vdev)
194  {
195  	return pmo_pdev_get_psoc(pmo_vdev_get_pdev(vdev));
196  }
197  
198  static inline struct pmo_psoc_priv_obj *
pmo_vdev_get_psoc_priv(struct wlan_objmgr_vdev * vdev)199  pmo_vdev_get_psoc_priv(struct wlan_objmgr_vdev *vdev)
200  {
201  	return pmo_psoc_get_priv(pmo_pdev_get_psoc(pmo_vdev_get_pdev(vdev)));
202  }
203  
204  #endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */
205  
206  #endif /* _WLAN_PMO_OBJMGR_H */
207