xref: /wlan-dirver/qca-wifi-host-cmn/umac/cfr/core/src/cfr_common.c (revision 861af9fad3d20cded5a90c420dd1ed901be32691)
1 /*
2  * Copyright (c) 2019-2020 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 #include <cfr_defs_i.h>
20 #include <qdf_types.h>
21 #include <wlan_objmgr_pdev_obj.h>
22 #include <wlan_objmgr_vdev_obj.h>
23 #include <wlan_objmgr_peer_obj.h>
24 #include <wlan_cfr_tgt_api.h>
25 #include <qdf_streamfs.h>
26 #include <target_if.h>
27 #include <wlan_osif_priv.h>
28 #include <cfg_ucfg_api.h>
29 #include "cfr_cfg.h"
30 
31 /**
32  * wlan_cfr_is_ini_disabled() - Check if cfr feature is disabled
33  * @pdev - the physical device object.
34  *
35  * Return : true if cfr is disabled, else false.
36  */
37 static bool
38 wlan_cfr_is_ini_disabled(struct wlan_objmgr_pdev *pdev)
39 {
40 	struct wlan_objmgr_psoc *psoc;
41 	uint8_t cfr_disable_bitmap;
42 
43 	psoc = wlan_pdev_get_psoc(pdev);
44 	if (!psoc) {
45 		cfr_err("psoc is null");
46 		return true;
47 	}
48 
49 	cfr_disable_bitmap = cfg_get(psoc, CFG_CFR_DISABLE);
50 
51 	if (cfr_disable_bitmap & (1 << wlan_objmgr_pdev_get_pdev_id(pdev))) {
52 		cfr_info("cfr is disabled for pdev[%d]",
53 			 wlan_objmgr_pdev_get_pdev_id(pdev));
54 		return true;
55 	}
56 
57 	return false;
58 }
59 
60 QDF_STATUS
61 wlan_cfr_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc, void *arg)
62 {
63 	struct psoc_cfr *cfr_sc = NULL;
64 
65 	cfr_sc = (struct psoc_cfr *)qdf_mem_malloc(sizeof(struct psoc_cfr));
66 	if (NULL == cfr_sc) {
67 		cfr_err("Failed to allocate cfr_ctx object\n");
68 		return QDF_STATUS_E_NOMEM;
69 	}
70 
71 	qdf_mem_zero(cfr_sc, sizeof(struct psoc_cfr));
72 	cfr_sc->psoc_obj = psoc;
73 
74 	wlan_objmgr_psoc_component_obj_attach(psoc, WLAN_UMAC_COMP_CFR,
75 					      (void *)cfr_sc,
76 					      QDF_STATUS_SUCCESS);
77 
78 	return QDF_STATUS_SUCCESS;
79 }
80 
81 QDF_STATUS
82 wlan_cfr_psoc_obj_destroy_handler(struct wlan_objmgr_psoc *psoc, void *arg)
83 {
84 	struct psoc_cfr *cfr_sc = NULL;
85 
86 	cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
87 						       WLAN_UMAC_COMP_CFR);
88 	if (NULL != cfr_sc) {
89 		wlan_objmgr_psoc_component_obj_detach(psoc, WLAN_UMAC_COMP_CFR,
90 						      (void *)cfr_sc);
91 		qdf_mem_free(cfr_sc);
92 	}
93 
94 	return QDF_STATUS_SUCCESS;
95 }
96 
97 QDF_STATUS
98 wlan_cfr_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg)
99 {
100 	struct pdev_cfr *pa = NULL;
101 
102 	if (NULL == pdev) {
103 		cfr_err("PDEV is NULL\n");
104 		return QDF_STATUS_E_FAILURE;
105 	}
106 
107 	if (wlan_cfr_is_ini_disabled(pdev)) {
108 		wlan_pdev_nif_feat_ext_cap_clear(pdev, WLAN_PDEV_FEXT_CFR_EN);
109 		return QDF_STATUS_E_NOSUPPORT;
110 	}
111 
112 	wlan_pdev_nif_feat_ext_cap_set(pdev, WLAN_PDEV_FEXT_CFR_EN);
113 
114 	pa = (struct pdev_cfr *)qdf_mem_malloc(sizeof(struct pdev_cfr));
115 	if (NULL == pa) {
116 		cfr_err("Failed to allocate pdev_cfr object\n");
117 		return QDF_STATUS_E_NOMEM;
118 	}
119 	qdf_mem_zero(pa, sizeof(struct pdev_cfr));
120 	pa->pdev_obj = pdev;
121 
122 	wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_UMAC_COMP_CFR,
123 					      (void *)pa, QDF_STATUS_SUCCESS);
124 
125 	return QDF_STATUS_SUCCESS;
126 }
127 
128 QDF_STATUS
129 wlan_cfr_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev, void *arg)
130 {
131 	struct pdev_cfr *pa = NULL;
132 
133 	if (NULL == pdev) {
134 		cfr_err("PDEV is NULL\n");
135 		return QDF_STATUS_E_FAILURE;
136 	}
137 
138 	if (wlan_cfr_is_feature_disabled(pdev)) {
139 		cfr_info("cfr is disabled");
140 		return QDF_STATUS_E_NOSUPPORT;
141 	}
142 
143 	pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR);
144 	if (NULL != pa) {
145 		wlan_objmgr_pdev_component_obj_detach(pdev, WLAN_UMAC_COMP_CFR,
146 						      (void *)pa);
147 		qdf_mem_free(pa);
148 	}
149 
150 	return QDF_STATUS_SUCCESS;
151 }
152 
153 QDF_STATUS
154 wlan_cfr_peer_obj_create_handler(struct wlan_objmgr_peer *peer, void *arg)
155 {
156 	struct peer_cfr *pe = NULL;
157 	struct wlan_objmgr_vdev *vdev;
158 	struct wlan_objmgr_pdev *pdev = NULL;
159 
160 	if (NULL == peer) {
161 		cfr_err("PEER is NULL\n");
162 		return QDF_STATUS_E_FAILURE;
163 	}
164 
165 	vdev = wlan_peer_get_vdev(peer);
166 	if (vdev)
167 		pdev = wlan_vdev_get_pdev(vdev);
168 
169 	if (!pdev) {
170 		cfr_err("PDEV is NULL\n");
171 		return QDF_STATUS_E_FAILURE;
172 	}
173 
174 	if (wlan_cfr_is_feature_disabled(pdev)) {
175 		cfr_info("cfr is disabled");
176 		return QDF_STATUS_E_NOSUPPORT;
177 	}
178 
179 	pe = (struct peer_cfr *)qdf_mem_malloc(sizeof(struct peer_cfr));
180 	if (NULL == pe) {
181 		cfr_err("Failed to allocate peer_cfr object\n");
182 		return QDF_STATUS_E_FAILURE;
183 	}
184 
185 	pe->peer_obj = peer;
186 
187 	/* Remaining will be populated when we give CFR capture command */
188 	wlan_objmgr_peer_component_obj_attach(peer, WLAN_UMAC_COMP_CFR,
189 					      (void *)pe, QDF_STATUS_SUCCESS);
190 	return QDF_STATUS_SUCCESS;
191 }
192 
193 QDF_STATUS
194 wlan_cfr_peer_obj_destroy_handler(struct wlan_objmgr_peer *peer, void *arg)
195 {
196 	struct peer_cfr *pe = NULL;
197 	struct wlan_objmgr_vdev *vdev;
198 	struct wlan_objmgr_pdev *pdev = NULL;
199 	struct pdev_cfr *pa = NULL;
200 
201 	if (NULL == peer) {
202 		cfr_err("PEER is NULL\n");
203 		return QDF_STATUS_E_FAILURE;
204 	}
205 
206 	vdev = wlan_peer_get_vdev(peer);
207 	if (vdev)
208 		pdev = wlan_vdev_get_pdev(vdev);
209 
210 	if (wlan_cfr_is_feature_disabled(pdev)) {
211 		cfr_info("cfr is disabled");
212 		return QDF_STATUS_E_NOSUPPORT;
213 	}
214 
215 	if (pdev)
216 		pa = wlan_objmgr_pdev_get_comp_private_obj(pdev,
217 							   WLAN_UMAC_COMP_CFR);
218 
219 	pe = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_CFR);
220 
221 	if (pa && pe) {
222 		if (pe->period && pe->request)
223 			pa->cfr_current_sta_count--;
224 	}
225 
226 	if (NULL != pe) {
227 		wlan_objmgr_peer_component_obj_detach(peer, WLAN_UMAC_COMP_CFR,
228 						      (void *)pe);
229 		qdf_mem_free(pe);
230 	}
231 
232 	return QDF_STATUS_SUCCESS;
233 }
234 
235 #ifdef CFR_USE_FIXED_FOLDER
236 static char *cfr_get_dev_name(struct wlan_objmgr_pdev *pdev)
237 {
238 	char *default_name = "wlan";
239 
240 	return default_name;
241 }
242 #else
243 /**
244  * cfr_get_dev_name() - Get net device name from pdev
245  *  @pdev: objmgr pdev
246  *
247  *  Return: netdev name
248  */
249 static char *cfr_get_dev_name(struct wlan_objmgr_pdev *pdev)
250 {
251 	struct pdev_osif_priv *pdev_ospriv;
252 	struct qdf_net_if *nif;
253 
254 	pdev_ospriv = wlan_pdev_get_ospriv(pdev);
255 	if (!pdev_ospriv) {
256 		cfr_err("pdev_ospriv is NULL\n");
257 		return NULL;
258 	}
259 
260 	nif = pdev_ospriv->nif;
261 	if (!nif) {
262 		cfr_err("pdev nif is NULL\n");
263 		return NULL;
264 	}
265 
266 	return  qdf_net_if_get_devname(nif);
267 }
268 #endif
269 
270 QDF_STATUS cfr_streamfs_init(struct wlan_objmgr_pdev *pdev)
271 {
272 	struct pdev_cfr *pa = NULL;
273 	char *devname;
274 	char folder[32];
275 
276 	if (!pdev) {
277 		cfr_err("PDEV is NULL\n");
278 		return QDF_STATUS_E_FAILURE;
279 	}
280 
281 	if (wlan_cfr_is_feature_disabled(pdev)) {
282 		cfr_info("cfr is disabled");
283 		return QDF_STATUS_COMP_DISABLED;
284 	}
285 
286 	pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR);
287 
288 	if (pa == NULL) {
289 		cfr_err("pdev_cfr is NULL\n");
290 		return QDF_STATUS_E_FAILURE;
291 	}
292 
293 	if (!pa->is_cfr_capable) {
294 		cfr_err("CFR IS NOT SUPPORTED\n");
295 		return QDF_STATUS_E_FAILURE;
296 	}
297 
298 	devname = cfr_get_dev_name(pdev);
299 	if (!devname) {
300 		cfr_err("devname is NULL\n");
301 		return QDF_STATUS_E_FAILURE;
302 	}
303 
304 	snprintf(folder, sizeof(folder), "cfr%s", devname);
305 
306 	pa->dir_ptr = qdf_streamfs_create_dir((const char *)folder, NULL);
307 
308 	if (!pa->dir_ptr) {
309 		cfr_err("Directory create failed");
310 		return QDF_STATUS_E_FAILURE;
311 	}
312 
313 	pa->chan_ptr = qdf_streamfs_open("cfr_dump", pa->dir_ptr,
314 					 pa->subbuf_size,
315 					 pa->num_subbufs, NULL);
316 
317 	if (!pa->chan_ptr) {
318 		cfr_err("Chan create failed");
319 		qdf_streamfs_remove_dir_recursive(pa->dir_ptr);
320 		pa->dir_ptr = NULL;
321 		return QDF_STATUS_E_FAILURE;
322 	}
323 
324 	return QDF_STATUS_SUCCESS;
325 }
326 
327 QDF_STATUS cfr_streamfs_remove(struct wlan_objmgr_pdev *pdev)
328 {
329 	struct pdev_cfr *pa = NULL;
330 
331 	if (wlan_cfr_is_feature_disabled(pdev)) {
332 		cfr_info("cfr is disabled");
333 		return QDF_STATUS_COMP_DISABLED;
334 	}
335 
336 	pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR);
337 	if (pa) {
338 		if (pa->chan_ptr) {
339 			qdf_streamfs_close(pa->chan_ptr);
340 			pa->chan_ptr = NULL;
341 		}
342 
343 		if (pa->dir_ptr) {
344 			qdf_streamfs_remove_dir_recursive(pa->dir_ptr);
345 			pa->dir_ptr = NULL;
346 		}
347 
348 	} else
349 		return QDF_STATUS_E_FAILURE;
350 
351 	return QDF_STATUS_SUCCESS;
352 }
353 
354 QDF_STATUS cfr_streamfs_write(struct pdev_cfr *pa, const void *write_data,
355 			      size_t write_len)
356 {
357 	if (pa->chan_ptr) {
358 
359 	/* write to channel buffer */
360 		qdf_streamfs_write(pa->chan_ptr, (const void *)write_data,
361 				   write_len);
362 	} else
363 		return QDF_STATUS_E_FAILURE;
364 
365 	return QDF_STATUS_SUCCESS;
366 }
367 
368 QDF_STATUS cfr_streamfs_flush(struct pdev_cfr *pa)
369 {
370 	if (pa->chan_ptr) {
371 
372 	/* Flush the data write to channel buffer */
373 		qdf_streamfs_flush(pa->chan_ptr);
374 	} else
375 		return QDF_STATUS_E_FAILURE;
376 
377 	return QDF_STATUS_SUCCESS;
378 }
379 
380 QDF_STATUS cfr_stop_indication(struct wlan_objmgr_vdev *vdev)
381 {
382 	struct pdev_cfr *pa;
383 	uint32_t status;
384 	struct wlan_objmgr_pdev *pdev;
385 
386 	pdev = wlan_vdev_get_pdev(vdev);
387 	pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR);
388 	if (!pa) {
389 		cfr_err("pdev_cfr is NULL\n");
390 		return QDF_STATUS_E_INVAL;
391 	}
392 
393 	status = cfr_streamfs_write(pa, (const void *)CFR_STOP_STR,
394 				    sizeof(CFR_STOP_STR));
395 
396 	status = cfr_streamfs_flush(pa);
397 	cfr_debug("stop indication done");
398 
399 	return status;
400 }
401