xref: /wlan-dirver/qca-wifi-host-cmn/umac/cp_stats/core/src/wlan_cp_stats_comp_handler.c (revision 92d87f51612f6c3b2285266215edee8911647c2f)
1 /*
2  * Copyright (c) 2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: wlan_cp_stats_comp_handler.c
21  *
22  * This file maintain definitions to APIs which handle attach/detach of other
23  * UMAC component specific cp stat object to cp stats
24  *
25  * Components calling configure API should alloc data structure while attaching
26  * dealloc while detaching, where as address for which to be deallocated will
27  * be passed back to component for data
28  */
29 #include "wlan_cp_stats_comp_handler.h"
30 #include "wlan_cp_stats_defs.h"
31 #include <wlan_cp_stats_ucfg_api.h>
32 #include <wlan_cp_stats_utils_api.h>
33 
34 static QDF_STATUS
35 wlan_cp_stats_psoc_comp_obj_config
36 (struct wlan_objmgr_psoc *psoc, enum wlan_cp_stats_comp_id comp_id,
37 	enum wlan_cp_stats_cfg_state cfg_state, void *data)
38 {
39 	struct psoc_cp_stats *psoc_cs;
40 
41 	psoc_cs = wlan_cp_stats_get_psoc_stats_obj(psoc);
42 	if (!psoc_cs) {
43 		cp_stats_err("psoc cp stats object is null");
44 		return QDF_STATUS_E_INVAL;
45 	}
46 
47 	wlan_cp_stats_psoc_obj_lock(psoc_cs);
48 	if (cfg_state == WLAN_CP_STATS_OBJ_ATTACH) {
49 		if (psoc_cs->psoc_comp_priv_obj[comp_id]) {
50 			wlan_cp_stats_psoc_obj_unlock(psoc_cs);
51 			return QDF_STATUS_E_EXISTS;
52 		}
53 		psoc_cs->psoc_comp_priv_obj[comp_id] = data;
54 	} else if (cfg_state == WLAN_CP_STATS_OBJ_DETACH) {
55 		if (psoc_cs->psoc_comp_priv_obj[comp_id] != data) {
56 			wlan_cp_stats_psoc_obj_unlock(psoc_cs);
57 			return QDF_STATUS_E_INVAL;
58 		}
59 		data = psoc_cs->psoc_comp_priv_obj[comp_id];
60 		psoc_cs->psoc_comp_priv_obj[comp_id] = NULL;
61 	} else if (cfg_state == WLAN_CP_STATS_OBJ_INVALID) {
62 		cp_stats_err("Invalid cp stats cfg_state");
63 		wlan_cp_stats_psoc_obj_unlock(psoc_cs);
64 		return QDF_STATUS_E_INVAL;
65 	}
66 
67 	wlan_cp_stats_psoc_obj_unlock(psoc_cs);
68 	return QDF_STATUS_SUCCESS;
69 }
70 
71 static QDF_STATUS
72 wlan_cp_stats_pdev_comp_obj_config
73 (struct wlan_objmgr_pdev *pdev, enum wlan_cp_stats_comp_id comp_id,
74 	enum wlan_cp_stats_cfg_state cfg_state, void *data)
75 {
76 	struct pdev_cp_stats *pdev_cs;
77 
78 	pdev_cs = wlan_cp_stats_get_pdev_stats_obj(pdev);
79 	if (!pdev_cs) {
80 		cp_stats_err("pdev cp stats object is null");
81 		return QDF_STATUS_E_INVAL;
82 	}
83 
84 	wlan_cp_stats_pdev_obj_lock(pdev_cs);
85 	if (cfg_state == WLAN_CP_STATS_OBJ_ATTACH) {
86 		if (pdev_cs->pdev_comp_priv_obj[comp_id]) {
87 			wlan_cp_stats_pdev_obj_unlock(pdev_cs);
88 			return QDF_STATUS_E_EXISTS;
89 		}
90 		pdev_cs->pdev_comp_priv_obj[comp_id] = data;
91 	} else if (cfg_state == WLAN_CP_STATS_OBJ_DETACH) {
92 		if (pdev_cs->pdev_comp_priv_obj[comp_id] != data) {
93 			wlan_cp_stats_pdev_obj_unlock(pdev_cs);
94 			return QDF_STATUS_E_INVAL;
95 		}
96 		data = pdev_cs->pdev_comp_priv_obj[comp_id];
97 		pdev_cs->pdev_comp_priv_obj[comp_id] = NULL;
98 	} else if (cfg_state == WLAN_CP_STATS_OBJ_INVALID) {
99 		cp_stats_err("Invalid cp stats cfg_state");
100 		wlan_cp_stats_pdev_obj_unlock(pdev_cs);
101 		return QDF_STATUS_E_INVAL;
102 	}
103 
104 	wlan_cp_stats_pdev_obj_unlock(pdev_cs);
105 	return QDF_STATUS_SUCCESS;
106 }
107 
108 static QDF_STATUS
109 wlan_cp_stats_vdev_comp_obj_config
110 (struct wlan_objmgr_vdev *vdev, enum wlan_cp_stats_comp_id comp_id,
111 	enum wlan_cp_stats_cfg_state cfg_state, void *data)
112 {
113 	struct vdev_cp_stats *vdev_cs;
114 
115 	vdev_cs = wlan_cp_stats_get_vdev_stats_obj(vdev);
116 	if (!vdev_cs) {
117 		cp_stats_err("vdev cp stats object is null");
118 		return QDF_STATUS_E_INVAL;
119 	}
120 
121 	wlan_cp_stats_vdev_obj_lock(vdev_cs);
122 	if (cfg_state == WLAN_CP_STATS_OBJ_ATTACH) {
123 		if (vdev_cs->vdev_comp_priv_obj[comp_id]) {
124 			wlan_cp_stats_vdev_obj_unlock(vdev_cs);
125 			return QDF_STATUS_E_EXISTS;
126 		}
127 		vdev_cs->vdev_comp_priv_obj[comp_id] = data;
128 	} else if (cfg_state == WLAN_CP_STATS_OBJ_DETACH) {
129 		if (vdev_cs->vdev_comp_priv_obj[comp_id] != data) {
130 			wlan_cp_stats_vdev_obj_unlock(vdev_cs);
131 			return QDF_STATUS_E_INVAL;
132 		}
133 		data = vdev_cs->vdev_comp_priv_obj[comp_id];
134 		vdev_cs->vdev_comp_priv_obj[comp_id] = NULL;
135 	} else if (cfg_state == WLAN_CP_STATS_OBJ_INVALID) {
136 		cp_stats_err("Invalid cp stats cfg_state");
137 		wlan_cp_stats_vdev_obj_unlock(vdev_cs);
138 		return QDF_STATUS_E_INVAL;
139 	}
140 
141 	wlan_cp_stats_vdev_obj_unlock(vdev_cs);
142 	return QDF_STATUS_SUCCESS;
143 }
144 
145 static QDF_STATUS
146 wlan_cp_stats_peer_comp_obj_config
147 (struct wlan_objmgr_peer *peer, enum wlan_cp_stats_comp_id comp_id,
148 	enum wlan_cp_stats_cfg_state cfg_state, void *data)
149 {
150 	struct peer_cp_stats *peer_cs;
151 
152 	peer_cs = wlan_cp_stats_get_peer_stats_obj(peer);
153 	if (!peer_cs) {
154 		cp_stats_err("peer cp stats object is null");
155 		return QDF_STATUS_E_INVAL;
156 	}
157 
158 	wlan_cp_stats_peer_obj_lock(peer_cs);
159 	if (cfg_state == WLAN_CP_STATS_OBJ_ATTACH) {
160 		if (peer_cs->peer_comp_priv_obj[comp_id]) {
161 			wlan_cp_stats_peer_obj_unlock(peer_cs);
162 			return QDF_STATUS_E_EXISTS;
163 		}
164 		peer_cs->peer_comp_priv_obj[comp_id] = data;
165 	} else if (cfg_state == WLAN_CP_STATS_OBJ_DETACH) {
166 		if (peer_cs->peer_comp_priv_obj[comp_id] != data) {
167 			wlan_cp_stats_peer_obj_unlock(peer_cs);
168 			return QDF_STATUS_E_INVAL;
169 		}
170 		data = peer_cs->peer_comp_priv_obj[comp_id];
171 		peer_cs->peer_comp_priv_obj[comp_id] = NULL;
172 	} else if (cfg_state == WLAN_CP_STATS_OBJ_INVALID) {
173 		cp_stats_err("Invalid cp stats cfg_state");
174 		wlan_cp_stats_peer_obj_unlock(peer_cs);
175 		return QDF_STATUS_E_INVAL;
176 	}
177 
178 	wlan_cp_stats_peer_obj_unlock(peer_cs);
179 	return QDF_STATUS_SUCCESS;
180 }
181 
182 QDF_STATUS
183 wlan_cp_stats_comp_obj_config(enum wlan_objmgr_obj_type obj_type,
184 			      enum wlan_cp_stats_cfg_state cfg_state,
185 			      enum wlan_cp_stats_comp_id comp_id,
186 			      void *cmn_obj, void *data)
187 {
188 	QDF_STATUS status;
189 
190 	if (!cmn_obj) {
191 		cp_stats_err("Common object is NULL");
192 		return QDF_STATUS_E_INVAL;
193 	}
194 
195 	/* component id is invalid */
196 	if (comp_id >= WLAN_CP_STATS_MAX_COMPONENTS) {
197 		cp_stats_err("Invalid component Id");
198 		return QDF_STATUS_MAXCOMP_FAIL;
199 	}
200 
201 	switch (obj_type) {
202 	case WLAN_PSOC_OP:
203 		status =
204 			wlan_cp_stats_psoc_comp_obj_config(
205 					(struct wlan_objmgr_psoc *)cmn_obj,
206 					comp_id, cfg_state, data);
207 		break;
208 	case WLAN_PDEV_OP:
209 		status =
210 			wlan_cp_stats_pdev_comp_obj_config(
211 					(struct wlan_objmgr_pdev *)cmn_obj,
212 					comp_id, cfg_state, data);
213 		break;
214 	case WLAN_VDEV_OP:
215 		status =
216 			wlan_cp_stats_vdev_comp_obj_config(
217 					(struct wlan_objmgr_vdev *)cmn_obj,
218 					comp_id, cfg_state, data);
219 		break;
220 	case WLAN_PEER_OP:
221 		status =
222 			wlan_cp_stats_peer_comp_obj_config(
223 					(struct wlan_objmgr_peer *)cmn_obj,
224 					comp_id, cfg_state, data);
225 		break;
226 	default:
227 		cp_stats_err("Invalid common object");
228 		return QDF_STATUS_E_INVAL;
229 	}
230 
231 	return status;
232 }
233