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