1 /*
2  * Copyright (c) 2018 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 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_DISA_OBJMGR_H
25 #define _WLAN_DISA_OBJMGR_H
26 
27 #include "wlan_objmgr_vdev_obj.h"
28 #include "wlan_objmgr_psoc_obj.h"
29 #include "wlan_disa_obj_mgmt_public_struct.h"
30 
31 /* Get/Put Ref */
32 
33 /**
34  * disa_psoc_get_ref() - DISA wrapper to increment ref count, if allowed
35  * @psoc: PSOC object
36  *
37  * DISA wrapper to increment ref count after checking valid object state
38  *
39  * Return: SUCCESS/FAILURE
40  */
disa_psoc_get_ref(struct wlan_objmgr_psoc * psoc)41 static inline QDF_STATUS disa_psoc_get_ref(struct wlan_objmgr_psoc *psoc)
42 {
43 	return wlan_objmgr_psoc_try_get_ref(psoc, WLAN_DISA_ID);
44 }
45 
46 /**
47  * disa_psoc_put_ref() - DISA wrapper to decrement ref count
48  * @psoc: PSOC object
49  *
50  * DISA wrapper to decrement ref count of psoc
51  *
52  * Return: SUCCESS/FAILURE
53  */
disa_psoc_put_ref(struct wlan_objmgr_psoc * psoc)54 static inline void disa_psoc_put_ref(struct wlan_objmgr_psoc *psoc)
55 {
56 	return wlan_objmgr_psoc_release_ref(psoc, WLAN_DISA_ID);
57 }
58 
59 /* Private Data */
60 
61 /**
62  * disa_psoc_get_priv_nolock(): DISA wrapper to retrieve component object
63  * @psoc: Psoc pointer
64  *
65  * DISA wrapper used to get the component private object pointer
66  *
67  * Return: Component private object
68  */
disa_psoc_get_priv_nolock(struct wlan_objmgr_psoc * psoc)69 static inline void *disa_psoc_get_priv_nolock(struct wlan_objmgr_psoc *psoc)
70 {
71 	return wlan_objmgr_psoc_get_comp_private_obj(psoc, WLAN_UMAC_COMP_DISA);
72 }
73 
74 /* Ids */
75 static inline uint8_t
disa_vdev_get_id(struct wlan_objmgr_vdev * vdev)76 disa_vdev_get_id(struct wlan_objmgr_vdev *vdev)
77 {
78 	uint8_t vdev_id;
79 
80 	vdev_id = wlan_vdev_get_id(vdev);
81 	QDF_BUG(vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS);
82 
83 	return vdev_id;
84 }
85 
86 /* Tree Navigation */
87 
88 /*
89  * !PLEASE READ!
90  *
91  * The following are objmgr navigation helpers for traversing objmgr object
92  * trees.
93  *
94  * Objmgr ensures parents of an objmgr object cannot be freed while a valid
95  * reference to one of its children is held. Based on this fact, all of these
96  * navigation helpers make the following assumptions to ensure safe usage:
97  *
98  * 1) The caller must hold a valid reference to the input objmgr object!
99  *	E.g. Use disa_[peer|vdev|pdev|psoc]_get_ref() on the input objmgr
100  *	object before using these APIs
101  * 2) Given assumption #1, the caller does not need to hold a reference to the
102  *	parents of the input objmgr object
103  * 3) Given assumption #1, parents of the input objmgr object cannot be null
104  * 4) Given assumption #1, private contexts of any parent of the input objmgr
105  *	object cannot be null
106  *
107  * These characteristics remove the need for most sanity checks when dealing
108  * with objmgr objects. However, please note that if you ever walk the tree
109  * from parent to child, references must be acquired all the way down!
110  *
111  * Example #1:
112  *
113  *	psoc = disa_vdev_get_psoc(vdev);
114  *	if (!psoc)
115  *		// this is dead code
116  *
117  * Example #2:
118  *
119  *	psoc_priv = disa_psoc_get_priv(psoc);
120  *	if (!psoc_priv)
121  *		// this is dead code
122  *
123  * Example #3:
124  *
125  *	status = disa_psoc_get_ref(psoc);
126  *
127  *	...
128  *
129  *	psoc = disa_vdev_get_psoc(vdev);
130  *
131  *	// the next line is redundant, don't do it!
132  *	status = disa_psoc_get_ref(psoc);
133  */
134 
135 /* Tree Navigation: psoc */
136 static inline struct disa_psoc_priv_obj *
disa_psoc_get_priv(struct wlan_objmgr_psoc * psoc)137 disa_psoc_get_priv(struct wlan_objmgr_psoc *psoc)
138 {
139 	struct disa_psoc_priv_obj *psoc_priv;
140 
141 	psoc_priv = disa_psoc_get_priv_nolock(psoc);
142 	QDF_BUG(psoc_priv);
143 
144 	return psoc_priv;
145 }
146 
147 static inline struct wlan_objmgr_vdev *
disa_psoc_get_vdev(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id)148 disa_psoc_get_vdev(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
149 {
150 	struct wlan_objmgr_vdev *vdev;
151 
152 	QDF_BUG(vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS);
153 	if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS)
154 		return NULL;
155 
156 	wlan_psoc_obj_lock(psoc);
157 	vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_id];
158 	wlan_psoc_obj_unlock(psoc);
159 
160 	return vdev;
161 }
162 
163 /* Tree Navigation: pdev */
164 static inline struct wlan_objmgr_psoc *
disa_pdev_get_psoc(struct wlan_objmgr_pdev * pdev)165 disa_pdev_get_psoc(struct wlan_objmgr_pdev *pdev)
166 {
167 	struct wlan_objmgr_psoc *psoc;
168 
169 	psoc = wlan_pdev_get_psoc(pdev);
170 	QDF_BUG(psoc);
171 
172 	return psoc;
173 }
174 
175 /* Tree Navigation: vdev */
176 static inline struct wlan_objmgr_pdev *
disa_vdev_get_pdev(struct wlan_objmgr_vdev * vdev)177 disa_vdev_get_pdev(struct wlan_objmgr_vdev *vdev)
178 {
179 	struct wlan_objmgr_pdev *pdev;
180 
181 	pdev = wlan_vdev_get_pdev(vdev);
182 	QDF_BUG(pdev);
183 
184 	return pdev;
185 }
186 
187 static inline struct wlan_objmgr_psoc *
disa_vdev_get_psoc(struct wlan_objmgr_vdev * vdev)188 disa_vdev_get_psoc(struct wlan_objmgr_vdev *vdev)
189 {
190 	return disa_pdev_get_psoc(disa_vdev_get_pdev(vdev));
191 }
192 
193 #endif /* _WLAN_DISA_OBJMGR_H */
194