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