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