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_QCA5332 || 157 target_type == TARGET_TYPE_QCN9224) { 158 /* No additional check required for these targets */ 159 status = 1; 160 } else { 161 if (!(period % CFR_MOD_PRD)) { 162 status = 1; 163 } else { 164 cfr_err("Invalid period value. Value must be mod of %d", 165 CFR_MOD_PRD); 166 } 167 } 168 return status; 169 } 170 171 QDF_STATUS tgt_cfr_init_pdev(struct wlan_objmgr_pdev *pdev) 172 { 173 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 174 QDF_STATUS status = QDF_STATUS_SUCCESS; 175 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 176 177 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 178 179 if (cfr_tx_ops->cfr_init_pdev) 180 status = cfr_tx_ops->cfr_init_pdev(psoc, pdev); 181 182 if (QDF_IS_STATUS_ERROR(status)) 183 cfr_err("Error occurred with exit code %d\n", status); 184 185 return status; 186 } 187 188 QDF_STATUS tgt_cfr_deinit_pdev(struct wlan_objmgr_pdev *pdev) 189 { 190 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 191 QDF_STATUS status = QDF_STATUS_SUCCESS; 192 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 193 194 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 195 196 if (cfr_tx_ops->cfr_deinit_pdev) 197 status = cfr_tx_ops->cfr_deinit_pdev(psoc, pdev); 198 199 if (QDF_IS_STATUS_ERROR(status)) 200 cfr_err("Error occurred with exit code %d\n", status); 201 202 return status; 203 } 204 205 int tgt_cfr_start_capture(struct wlan_objmgr_pdev *pdev, 206 struct wlan_objmgr_peer *peer, 207 struct cfr_capture_params *cfr_params) 208 { 209 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 210 int status = 0; 211 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 212 213 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 214 215 if (cfr_tx_ops->cfr_start_capture) 216 status = cfr_tx_ops->cfr_start_capture(pdev, peer, cfr_params); 217 218 if (status != 0) 219 cfr_err("Error occurred with exit code %d\n", status); 220 221 return status; 222 } 223 224 int tgt_cfr_stop_capture(struct wlan_objmgr_pdev *pdev, 225 struct wlan_objmgr_peer *peer) 226 { 227 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 228 int status = 0; 229 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 230 231 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 232 233 if (cfr_tx_ops->cfr_stop_capture) 234 status = cfr_tx_ops->cfr_stop_capture(pdev, peer); 235 236 if (status != 0) 237 cfr_err("Error occurred with exit code %d\n", status); 238 239 return status; 240 } 241 242 int 243 tgt_cfr_enable_cfr_timer(struct wlan_objmgr_pdev *pdev, uint32_t cfr_timer) 244 { 245 int status = 0; 246 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 247 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 248 249 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 250 251 if (cfr_tx_ops->cfr_enable_cfr_timer) 252 status = cfr_tx_ops->cfr_enable_cfr_timer(pdev, cfr_timer); 253 254 if (status != 0) 255 cfr_err("Error occurred with exit code %d\n", status); 256 257 return status; 258 } 259 260 #ifdef WLAN_ENH_CFR_ENABLE 261 QDF_STATUS 262 tgt_cfr_config_rcc(struct wlan_objmgr_pdev *pdev, 263 struct cfr_rcc_param *rcc_param) 264 { 265 QDF_STATUS status = QDF_STATUS_SUCCESS; 266 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 267 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 268 269 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 270 271 if (cfr_tx_ops->cfr_config_rcc) 272 status = cfr_tx_ops->cfr_config_rcc(pdev, rcc_param); 273 274 if (status != QDF_STATUS_SUCCESS) 275 cfr_err("Error occurred with exit code %d\n", status); 276 277 return status; 278 } 279 280 void tgt_cfr_start_lut_age_timer(struct wlan_objmgr_pdev *pdev) 281 { 282 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 283 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 284 285 if (!psoc) { 286 cfr_err("Invalid PSOC: Flush LUT Timer cannot be started\n"); 287 return; 288 } 289 290 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 291 292 if (cfr_tx_ops->cfr_start_lut_timer) 293 cfr_tx_ops->cfr_start_lut_timer(pdev); 294 } 295 296 void tgt_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev *pdev) 297 { 298 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 299 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 300 301 if (!psoc) { 302 cfr_err("Invalid PSOC: Flush LUT Timer cannot be stopped\n"); 303 return; 304 } 305 306 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 307 308 if (cfr_tx_ops->cfr_stop_lut_timer) 309 cfr_tx_ops->cfr_stop_lut_timer(pdev); 310 } 311 312 void tgt_cfr_default_ta_ra_cfg(struct wlan_objmgr_pdev *pdev, 313 struct cfr_rcc_param *rcc_param, 314 bool allvalid, uint16_t reset_cfg) 315 { 316 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 317 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 318 319 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 320 321 if (cfr_tx_ops->cfr_default_ta_ra_cfg) 322 cfr_tx_ops->cfr_default_ta_ra_cfg(rcc_param, 323 allvalid, reset_cfg); 324 } 325 326 void tgt_cfr_dump_lut_enh(struct wlan_objmgr_pdev *pdev) 327 { 328 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 329 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 330 331 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 332 333 if (cfr_tx_ops->cfr_dump_lut_enh) 334 cfr_tx_ops->cfr_dump_lut_enh(pdev); 335 } 336 337 void tgt_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf) 338 { 339 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 340 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 341 342 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 343 344 if (cfr_tx_ops->cfr_rx_tlv_process) 345 cfr_tx_ops->cfr_rx_tlv_process(pdev, nbuf); 346 } 347 348 void tgt_cfr_update_global_cfg(struct wlan_objmgr_pdev *pdev) 349 { 350 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 351 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 352 353 if (!psoc) { 354 cfr_err("Invalid PSOC:Cannot update global config.\n"); 355 return; 356 } 357 358 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 359 360 if (cfr_tx_ops->cfr_update_global_cfg) 361 cfr_tx_ops->cfr_update_global_cfg(pdev); 362 } 363 364 QDF_STATUS tgt_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev *pdev, 365 bool is_subscribe) 366 { 367 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; 368 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 369 370 if (!psoc) { 371 cfr_err("Invalid psoc\n"); 372 return QDF_STATUS_E_INVAL; 373 } 374 375 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); 376 377 if (cfr_tx_ops->cfr_subscribe_ppdu_desc) 378 return cfr_tx_ops->cfr_subscribe_ppdu_desc(pdev, 379 is_subscribe); 380 381 return QDF_STATUS_SUCCESS; 382 } 383 384 QDF_STATUS 385 tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc *psoc, 386 uint32_t value) 387 { 388 struct psoc_cfr *cfr_sc; 389 390 if (!psoc) { 391 cfr_err("CFR: NULL PSOC!!"); 392 return QDF_STATUS_E_INVAL; 393 } 394 395 cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 396 WLAN_UMAC_COMP_CFR); 397 398 if (!cfr_sc) { 399 cfr_err("Failed to get CFR component priv obj!!"); 400 return QDF_STATUS_E_INVAL; 401 } 402 403 cfr_sc->is_cap_interval_mode_sel_support = !!value; 404 cfr_debug("CFR: cap_interval_mode_sel_support is %s\n", 405 (cfr_sc->is_cap_interval_mode_sel_support) ? 406 "enabled" : 407 "disabled"); 408 409 return QDF_STATUS_SUCCESS; 410 } 411 412 QDF_STATUS 413 tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value) 414 { 415 struct psoc_cfr *cfr_sc; 416 417 if (!psoc) { 418 cfr_err("CFR: NULL PSOC!!"); 419 return QDF_STATUS_E_INVAL; 420 } 421 422 cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 423 WLAN_UMAC_COMP_CFR); 424 if (!cfr_sc) { 425 cfr_err("Failed to get CFR component priv obj!!"); 426 return QDF_STATUS_E_INVAL; 427 } 428 429 cfr_sc->is_mo_marking_support = !!value; 430 cfr_debug("CFR: mo_marking_support is %s\n", 431 (cfr_sc->is_mo_marking_support) ? "enabled" : "disabled"); 432 433 return QDF_STATUS_SUCCESS; 434 } 435 436 QDF_STATUS 437 tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value) 438 { 439 struct psoc_cfr *cfr_sc; 440 441 if (!psoc) { 442 cfr_err("CFR: NULL PSOC!!"); 443 return QDF_STATUS_E_INVAL; 444 } 445 446 cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 447 WLAN_UMAC_COMP_CFR); 448 449 if (!cfr_sc) { 450 cfr_err("Failed to get CFR component priv obj!!"); 451 return QDF_STATUS_E_INVAL; 452 } 453 454 cfr_sc->is_aoa_for_rcc_support = !!value; 455 cfr_debug("CFR: aoa_for_rcc_support is %s\n", 456 (cfr_sc->is_aoa_for_rcc_support) ? "enabled" : "disabled"); 457 458 return QDF_STATUS_SUCCESS; 459 } 460 #else 461 QDF_STATUS 462 tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc *psoc, 463 uint32_t value) 464 { 465 return QDF_STATUS_E_NOSUPPORT; 466 } 467 468 QDF_STATUS 469 tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc *psoc, 470 uint32_t value) 471 { 472 return QDF_STATUS_E_NOSUPPORT; 473 } 474 475 QDF_STATUS 476 tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value) 477 { 478 return QDF_STATUS_E_NOSUPPORT; 479 } 480 #endif 481