1 /* 2 * Copyright (c) 2019-2021 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 * Layer b/w umac and target_if (ol) txops 21 * It contains wrapers for txops 22 */ 23 24 #include <wlan_cfr_tgt_api.h> 25 #include <wlan_cfr_utils_api.h> 26 #include <target_type.h> 27 #include <cfr_defs_i.h> 28 29 uint32_t tgt_cfr_info_send(struct wlan_objmgr_pdev *pdev, void *head, 30 size_t hlen, void *data, size_t dlen, void *tail, 31 size_t tlen) 32 { 33 struct pdev_cfr *pa; 34 uint32_t status, total_len; 35 uint8_t *nl_data = NULL; 36 37 pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); 38 39 if (pa == NULL) { 40 cfr_err("pdev_cfr is NULL\n"); 41 return -1; 42 } 43 44 /* If CFR data transport mode is NL event then send single event*/ 45 if (pa->nl_cb.cfr_nl_cb) { 46 total_len = hlen + dlen + tlen; 47 48 nl_data = qdf_mem_malloc(total_len); 49 if (!nl_data) { 50 cfr_err("failed to alloc memory, len %d, vdev_id %d", 51 total_len, pa->nl_cb.vdev_id); 52 return QDF_STATUS_E_FAILURE; 53 } 54 55 if (hlen) 56 qdf_mem_copy(nl_data, head, hlen); 57 58 if (dlen) 59 qdf_mem_copy(nl_data + hlen, data, dlen); 60 61 if (tlen) 62 qdf_mem_copy(nl_data + hlen + dlen, tail, tlen); 63 64 pa->nl_cb.cfr_nl_cb(pa->nl_cb.vdev_id, pa->nl_cb.pid, 65 (const void *)nl_data, total_len); 66 qdf_mem_free(nl_data); 67 68 return QDF_STATUS_SUCCESS; 69 } 70 71 if (head) 72 status = cfr_streamfs_write(pa, (const void *)head, hlen); 73 74 if (data) 75 status = cfr_streamfs_write(pa, (const void *)data, dlen); 76 77 if (tail) 78 status = cfr_streamfs_write(pa, (const void *)tail, tlen); 79 80 81 /* finalise the write */ 82 status = cfr_streamfs_flush(pa); 83 84 return status; 85 } 86 87 void tgt_cfr_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value) 88 { 89 struct psoc_cfr *cfr_sc; 90 91 if (psoc == NULL) 92 return; 93 94 cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 95 WLAN_UMAC_COMP_CFR); 96 if (cfr_sc == NULL) 97 return; 98 99 cfr_sc->is_cfr_capable = !!value; 100 cfr_debug("CFR: FW support advert=%d", cfr_sc->is_cfr_capable); 101 } 102 103 static inline struct wlan_lmac_if_cfr_tx_ops * 104 wlan_psoc_get_cfr_txops(struct wlan_objmgr_psoc *psoc) 105 { 106 struct wlan_lmac_if_tx_ops *tx_ops; 107 108 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 109 if (!tx_ops) { 110 cfr_err("tx_ops is NULL"); 111 return NULL; 112 } 113 return &tx_ops->cfr_tx_ops; 114 } 115 116 int tgt_cfr_get_target_type(struct wlan_objmgr_psoc *psoc) 117 { 118 uint32_t target_type = 0; 119 struct wlan_lmac_if_target_tx_ops *target_type_tx_ops; 120 struct wlan_lmac_if_tx_ops *tx_ops; 121 122 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 123 if (!tx_ops) { 124 cfr_err("tx_ops is NULL"); 125 return target_type; 126 } 127 target_type_tx_ops = &tx_ops->target_tx_ops; 128 129 if (target_type_tx_ops->tgt_get_tgt_type) 130 target_type = target_type_tx_ops->tgt_get_tgt_type(psoc); 131 132 return target_type; 133 } 134 135 int tgt_cfr_validate_period(struct wlan_objmgr_psoc *psoc, u_int32_t period) 136 { 137 uint32_t target_type = tgt_cfr_get_target_type(psoc); 138 int status = 0; 139 140 if (target_type == TARGET_TYPE_UNKNOWN) { 141 cfr_err("cfr period validation fail due to invalid target type"); 142 return status; 143 } 144 145 /* Basic check is the period should be between 0 and MAX_CFR_PRD */ 146 if ((period < 0) || (period > MAX_CFR_PRD)) { 147 cfr_err("Invalid period value: %d\n", period); 148 return status; 149 } 150 151 if (target_type == TARGET_TYPE_QCN9000 || 152 target_type == TARGET_TYPE_QCA6018 || 153 target_type == TARGET_TYPE_QCA8074V2 || 154 target_type == TARGET_TYPE_QCA5018) { 155 /* No additional check required for these targets */ 156 status = 1; 157 } else { 158 if (!(period % CFR_MOD_PRD)) { 159 status = 1; 160 } else { 161 cfr_err("Invalid period value. Value must be mod of %d", 162 CFR_MOD_PRD); 163 } 164 } 165 return status; 166 } 167 168 QDF_STATUS tgt_cfr_init_pdev(struct wlan_objmgr_pdev *pdev) 169 { 170 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 171 QDF_STATUS status = QDF_STATUS_SUCCESS; 172 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 173 174 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 175 176 if (cfr_tx_ops->cfr_init_pdev) 177 status = cfr_tx_ops->cfr_init_pdev(psoc, pdev); 178 179 if (QDF_IS_STATUS_ERROR(status)) 180 cfr_err("Error occurred with exit code %d\n", status); 181 182 return status; 183 } 184 185 QDF_STATUS tgt_cfr_deinit_pdev(struct wlan_objmgr_pdev *pdev) 186 { 187 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 188 QDF_STATUS status = QDF_STATUS_SUCCESS; 189 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 190 191 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 192 193 if (cfr_tx_ops->cfr_deinit_pdev) 194 status = cfr_tx_ops->cfr_deinit_pdev(psoc, pdev); 195 196 if (QDF_IS_STATUS_ERROR(status)) 197 cfr_err("Error occurred with exit code %d\n", status); 198 199 return status; 200 } 201 202 int tgt_cfr_start_capture(struct wlan_objmgr_pdev *pdev, 203 struct wlan_objmgr_peer *peer, 204 struct cfr_capture_params *cfr_params) 205 { 206 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 207 int status = 0; 208 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 209 210 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 211 212 if (cfr_tx_ops->cfr_start_capture) 213 status = cfr_tx_ops->cfr_start_capture(pdev, peer, cfr_params); 214 215 if (status != 0) 216 cfr_err("Error occurred with exit code %d\n", status); 217 218 return status; 219 } 220 221 int tgt_cfr_stop_capture(struct wlan_objmgr_pdev *pdev, 222 struct wlan_objmgr_peer *peer) 223 { 224 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 225 int status = 0; 226 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 227 228 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 229 230 if (cfr_tx_ops->cfr_stop_capture) 231 status = cfr_tx_ops->cfr_stop_capture(pdev, peer); 232 233 if (status != 0) 234 cfr_err("Error occurred with exit code %d\n", status); 235 236 return status; 237 } 238 239 int 240 tgt_cfr_enable_cfr_timer(struct wlan_objmgr_pdev *pdev, uint32_t cfr_timer) 241 { 242 int status = 0; 243 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 244 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 245 246 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 247 248 if (cfr_tx_ops->cfr_enable_cfr_timer) 249 status = cfr_tx_ops->cfr_enable_cfr_timer(pdev, cfr_timer); 250 251 if (status != 0) 252 cfr_err("Error occurred with exit code %d\n", status); 253 254 return status; 255 } 256 257 #ifdef WLAN_ENH_CFR_ENABLE 258 QDF_STATUS 259 tgt_cfr_config_rcc(struct wlan_objmgr_pdev *pdev, 260 struct cfr_rcc_param *rcc_param) 261 { 262 QDF_STATUS status = QDF_STATUS_SUCCESS; 263 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 264 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 265 266 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 267 268 if (cfr_tx_ops->cfr_config_rcc) 269 status = cfr_tx_ops->cfr_config_rcc(pdev, rcc_param); 270 271 if (status != QDF_STATUS_SUCCESS) 272 cfr_err("Error occurred with exit code %d\n", status); 273 274 return status; 275 } 276 277 void tgt_cfr_start_lut_age_timer(struct wlan_objmgr_pdev *pdev) 278 { 279 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 280 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 281 282 if (!psoc) { 283 cfr_err("Invalid PSOC: Flush LUT Timer cannot be started\n"); 284 return; 285 } 286 287 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 288 289 if (cfr_tx_ops->cfr_start_lut_timer) 290 cfr_tx_ops->cfr_start_lut_timer(pdev); 291 } 292 293 void tgt_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev *pdev) 294 { 295 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 296 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 297 298 if (!psoc) { 299 cfr_err("Invalid PSOC: Flush LUT Timer cannot be stopped\n"); 300 return; 301 } 302 303 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 304 305 if (cfr_tx_ops->cfr_stop_lut_timer) 306 cfr_tx_ops->cfr_stop_lut_timer(pdev); 307 } 308 309 void tgt_cfr_default_ta_ra_cfg(struct wlan_objmgr_pdev *pdev, 310 struct cfr_rcc_param *rcc_param, 311 bool allvalid, uint16_t reset_cfg) 312 { 313 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 314 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 315 316 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 317 318 if (cfr_tx_ops->cfr_default_ta_ra_cfg) 319 cfr_tx_ops->cfr_default_ta_ra_cfg(rcc_param, 320 allvalid, reset_cfg); 321 } 322 323 void tgt_cfr_dump_lut_enh(struct wlan_objmgr_pdev *pdev) 324 { 325 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 326 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 327 328 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 329 330 if (cfr_tx_ops->cfr_dump_lut_enh) 331 cfr_tx_ops->cfr_dump_lut_enh(pdev); 332 } 333 334 void tgt_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf) 335 { 336 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 337 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 338 339 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 340 341 if (cfr_tx_ops->cfr_rx_tlv_process) 342 cfr_tx_ops->cfr_rx_tlv_process(pdev, nbuf); 343 } 344 345 void tgt_cfr_update_global_cfg(struct wlan_objmgr_pdev *pdev) 346 { 347 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 348 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 349 350 if (!psoc) { 351 cfr_err("Invalid PSOC:Cannot update global config.\n"); 352 return; 353 } 354 355 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 356 357 if (cfr_tx_ops->cfr_update_global_cfg) 358 cfr_tx_ops->cfr_update_global_cfg(pdev); 359 } 360 361 QDF_STATUS tgt_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev *pdev, 362 bool is_subscribe) 363 { 364 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 365 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 366 367 if (!psoc) { 368 cfr_err("Invalid psoc\n"); 369 return QDF_STATUS_E_INVAL; 370 } 371 372 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 373 374 if (cfr_tx_ops->cfr_subscribe_ppdu_desc) 375 return cfr_tx_ops->cfr_subscribe_ppdu_desc(pdev, 376 is_subscribe); 377 378 return QDF_STATUS_SUCCESS; 379 } 380 381 QDF_STATUS 382 tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc *psoc, 383 uint32_t value) 384 { 385 struct psoc_cfr *cfr_sc; 386 387 if (!psoc) { 388 cfr_err("CFR: NULL PSOC!!"); 389 return QDF_STATUS_E_INVAL; 390 } 391 392 cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 393 WLAN_UMAC_COMP_CFR); 394 395 if (!cfr_sc) { 396 cfr_err("Failed to get CFR component priv obj!!"); 397 return QDF_STATUS_E_INVAL; 398 } 399 400 cfr_sc->is_cap_interval_mode_sel_support = !!value; 401 cfr_debug("CFR: cap_interval_mode_sel_support is %s\n", 402 (cfr_sc->is_cap_interval_mode_sel_support) ? 403 "enabled" : 404 "disabled"); 405 406 return QDF_STATUS_SUCCESS; 407 } 408 409 QDF_STATUS 410 tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value) 411 { 412 struct psoc_cfr *cfr_sc; 413 414 if (!psoc) { 415 cfr_err("CFR: NULL PSOC!!"); 416 return QDF_STATUS_E_INVAL; 417 } 418 419 cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 420 WLAN_UMAC_COMP_CFR); 421 if (!cfr_sc) { 422 cfr_err("Failed to get CFR component priv obj!!"); 423 return QDF_STATUS_E_INVAL; 424 } 425 426 cfr_sc->is_mo_marking_support = !!value; 427 cfr_debug("CFR: mo_marking_support is %s\n", 428 (cfr_sc->is_mo_marking_support) ? "enabled" : "disabled"); 429 430 return QDF_STATUS_SUCCESS; 431 } 432 433 QDF_STATUS 434 tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value) 435 { 436 struct psoc_cfr *cfr_sc; 437 438 if (!psoc) { 439 cfr_err("CFR: NULL PSOC!!"); 440 return QDF_STATUS_E_INVAL; 441 } 442 443 cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 444 WLAN_UMAC_COMP_CFR); 445 446 if (!cfr_sc) { 447 cfr_err("Failed to get CFR component priv obj!!"); 448 return QDF_STATUS_E_INVAL; 449 } 450 451 cfr_sc->is_aoa_for_rcc_support = !!value; 452 cfr_debug("CFR: aoa_for_rcc_support is %s\n", 453 (cfr_sc->is_aoa_for_rcc_support) ? "enabled" : "disabled"); 454 455 return QDF_STATUS_SUCCESS; 456 } 457 #else 458 QDF_STATUS 459 tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc *psoc, 460 uint32_t value) 461 { 462 return QDF_STATUS_E_NOSUPPORT; 463 } 464 465 QDF_STATUS 466 tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc *psoc, 467 uint32_t value) 468 { 469 return QDF_STATUS_E_NOSUPPORT; 470 } 471 472 QDF_STATUS 473 tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value) 474 { 475 return QDF_STATUS_E_NOSUPPORT; 476 } 477 #endif 478