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