1 /* 2 * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. 3 * 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 #include <wlan_spectral_utils_api.h> 21 #include <qdf_module.h> 22 #include "../../core/spectral_cmn_api_i.h" 23 #include <wlan_spectral_tgt_api.h> 24 #include <cfg_ucfg_api.h> 25 26 bool wlan_spectral_is_feature_disabled(struct wlan_objmgr_psoc *psoc) 27 { 28 if (!psoc) { 29 spectral_err("PSOC is NULL!"); 30 return true; 31 } 32 33 if (wlan_psoc_nif_feat_cap_get(psoc, WLAN_SOC_F_SPECTRAL_DISABLE)) 34 return true; 35 36 return false; 37 } 38 39 QDF_STATUS 40 wlan_spectral_init(void) 41 { 42 if (wlan_objmgr_register_psoc_create_handler( 43 WLAN_UMAC_COMP_SPECTRAL, 44 wlan_spectral_psoc_obj_create_handler, 45 NULL) != 46 QDF_STATUS_SUCCESS) { 47 return QDF_STATUS_E_FAILURE; 48 } 49 if (wlan_objmgr_register_psoc_destroy_handler( 50 WLAN_UMAC_COMP_SPECTRAL, 51 wlan_spectral_psoc_obj_destroy_handler, 52 NULL) != 53 QDF_STATUS_SUCCESS) { 54 return QDF_STATUS_E_FAILURE; 55 } 56 if (wlan_objmgr_register_pdev_create_handler( 57 WLAN_UMAC_COMP_SPECTRAL, 58 wlan_spectral_pdev_obj_create_handler, 59 NULL) != 60 QDF_STATUS_SUCCESS) { 61 return QDF_STATUS_E_FAILURE; 62 } 63 if (wlan_objmgr_register_pdev_destroy_handler( 64 WLAN_UMAC_COMP_SPECTRAL, 65 wlan_spectral_pdev_obj_destroy_handler, 66 NULL) != 67 QDF_STATUS_SUCCESS) { 68 return QDF_STATUS_E_FAILURE; 69 } 70 71 return QDF_STATUS_SUCCESS; 72 } 73 74 QDF_STATUS 75 wlan_spectral_deinit(void) 76 { 77 if (wlan_objmgr_unregister_psoc_create_handler( 78 WLAN_UMAC_COMP_SPECTRAL, 79 wlan_spectral_psoc_obj_create_handler, 80 NULL) != 81 QDF_STATUS_SUCCESS) { 82 return QDF_STATUS_E_FAILURE; 83 } 84 if (wlan_objmgr_unregister_psoc_destroy_handler( 85 WLAN_UMAC_COMP_SPECTRAL, 86 wlan_spectral_psoc_obj_destroy_handler, 87 NULL) != 88 QDF_STATUS_SUCCESS) { 89 return QDF_STATUS_E_FAILURE; 90 } 91 if (wlan_objmgr_unregister_pdev_create_handler( 92 WLAN_UMAC_COMP_SPECTRAL, 93 wlan_spectral_pdev_obj_create_handler, 94 NULL) != 95 QDF_STATUS_SUCCESS) { 96 return QDF_STATUS_E_FAILURE; 97 } 98 if (wlan_objmgr_unregister_pdev_destroy_handler( 99 WLAN_UMAC_COMP_SPECTRAL, 100 wlan_spectral_pdev_obj_destroy_handler, 101 NULL) != 102 QDF_STATUS_SUCCESS) { 103 return QDF_STATUS_E_FAILURE; 104 } 105 return QDF_STATUS_SUCCESS; 106 } 107 108 QDF_STATUS 109 spectral_register_legacy_cb(struct wlan_objmgr_psoc *psoc, 110 struct spectral_legacy_cbacks *legacy_cbacks) 111 { 112 struct spectral_context *sc; 113 114 sc = spectral_get_spectral_ctx_from_psoc(psoc); 115 if (!sc) { 116 spectral_err("Invalid Context"); 117 return QDF_STATUS_E_FAILURE; 118 } 119 120 sc->legacy_cbacks.vdev_get_chan_freq = 121 legacy_cbacks->vdev_get_chan_freq; 122 sc->legacy_cbacks.vdev_get_chan_freq_seg2 = 123 legacy_cbacks->vdev_get_chan_freq_seg2; 124 sc->legacy_cbacks.vdev_get_ch_width = legacy_cbacks->vdev_get_ch_width; 125 sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz = 126 legacy_cbacks->vdev_get_sec20chan_freq_mhz; 127 128 return QDF_STATUS_SUCCESS; 129 } 130 qdf_export_symbol(spectral_register_legacy_cb); 131 132 int16_t 133 spectral_vdev_get_chan_freq(struct wlan_objmgr_vdev *vdev) 134 { 135 struct spectral_context *sc; 136 137 sc = spectral_get_spectral_ctx_from_vdev(vdev); 138 if (!sc) { 139 spectral_err("spectral context is Null"); 140 return -EINVAL; 141 } 142 143 if (!sc->legacy_cbacks.vdev_get_chan_freq) { 144 spectral_err("vdev_get_chan_freq is not supported"); 145 return -ENOTSUPP; 146 } 147 148 return sc->legacy_cbacks.vdev_get_chan_freq(vdev); 149 } 150 151 int16_t 152 spectral_vdev_get_chan_freq_seg2(struct wlan_objmgr_vdev *vdev) 153 { 154 struct spectral_context *sc; 155 156 sc = spectral_get_spectral_ctx_from_vdev(vdev); 157 if (!sc) { 158 spectral_err("spectral context is null"); 159 return -EINVAL; 160 } 161 162 if (!sc->legacy_cbacks.vdev_get_chan_freq_seg2) { 163 spectral_err("vdev_get_chan_freq_seg2 is not supported"); 164 return -ENOTSUPP; 165 } 166 167 return sc->legacy_cbacks.vdev_get_chan_freq_seg2(vdev); 168 } 169 170 enum phy_ch_width 171 spectral_vdev_get_ch_width(struct wlan_objmgr_vdev *vdev) 172 { 173 struct spectral_context *sc; 174 175 sc = spectral_get_spectral_ctx_from_vdev(vdev); 176 if (!sc) { 177 spectral_err("spectral context is Null"); 178 return CH_WIDTH_INVALID; 179 } 180 181 if (!sc->legacy_cbacks.vdev_get_ch_width) { 182 spectral_err("vdev_get_ch_width is not supported"); 183 return -ENOTSUPP; 184 } 185 186 return sc->legacy_cbacks.vdev_get_ch_width(vdev); 187 } 188 189 int 190 spectral_vdev_get_sec20chan_freq_mhz(struct wlan_objmgr_vdev *vdev, 191 uint16_t *sec20chan_freq) 192 { 193 struct spectral_context *sc; 194 195 sc = spectral_get_spectral_ctx_from_vdev(vdev); 196 if (!sc) { 197 spectral_err("spectral context is Null"); 198 return -EINVAL; 199 } 200 201 if (!sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz) { 202 spectral_err("vdev_get_sec20chan_freq_mhz is not supported"); 203 return -ENOTSUPP; 204 } 205 206 return sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz(vdev, 207 sec20chan_freq); 208 } 209 210 void 211 wlan_lmac_if_sptrl_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 212 { 213 struct wlan_lmac_if_sptrl_rx_ops *sptrl_rx_ops = &rx_ops->sptrl_rx_ops; 214 215 /* Spectral rx ops */ 216 sptrl_rx_ops->sptrlro_get_pdev_target_handle = 217 tgt_get_pdev_target_handle; 218 sptrl_rx_ops->sptrlro_get_psoc_target_handle = 219 tgt_get_psoc_target_handle; 220 sptrl_rx_ops->sptrlro_vdev_get_chan_freq = spectral_vdev_get_chan_freq; 221 sptrl_rx_ops->sptrlro_vdev_get_chan_freq_seg2 = 222 spectral_vdev_get_chan_freq_seg2; 223 sptrl_rx_ops->sptrlro_vdev_get_ch_width = spectral_vdev_get_ch_width; 224 sptrl_rx_ops->sptrlro_vdev_get_sec20chan_freq_mhz = 225 spectral_vdev_get_sec20chan_freq_mhz; 226 sptrl_rx_ops->sptrlro_spectral_is_feature_disabled = 227 wlan_spectral_is_feature_disabled; 228 } 229 230 QDF_STATUS 231 wlan_register_spectral_wmi_ops(struct wlan_objmgr_psoc *psoc, 232 struct spectral_wmi_ops *wmi_ops) 233 { 234 struct spectral_context *sc; 235 236 if (!psoc) { 237 spectral_err("psoc is NULL!"); 238 return QDF_STATUS_E_INVAL; 239 } 240 241 sc = spectral_get_spectral_ctx_from_psoc(psoc); 242 if (!sc) { 243 spectral_err("spectral context is NULL!"); 244 return QDF_STATUS_E_FAILURE; 245 } 246 247 return sc->sptrlc_register_spectral_wmi_ops(psoc, wmi_ops); 248 } 249 250 qdf_export_symbol(wlan_register_spectral_wmi_ops); 251 252 QDF_STATUS 253 wlan_register_spectral_tgt_ops(struct wlan_objmgr_psoc *psoc, 254 struct spectral_tgt_ops *tgt_ops) 255 { 256 struct spectral_context *sc; 257 258 if (!psoc) { 259 spectral_err("psoc is NULL!"); 260 return QDF_STATUS_E_INVAL; 261 } 262 263 sc = spectral_get_spectral_ctx_from_psoc(psoc); 264 if (!sc) { 265 spectral_err("spectral context is NULL!"); 266 return QDF_STATUS_E_FAILURE; 267 } 268 269 return sc->sptrlc_register_spectral_tgt_ops(psoc, tgt_ops); 270 } 271 272 qdf_export_symbol(wlan_register_spectral_tgt_ops); 273 274 /** 275 * wlan_spectral_psoc_target_attach() - Spectral psoc target attach 276 * @psoc: pointer to psoc object 277 * 278 * API to initialize Spectral psoc target object 279 * 280 * Return: QDF_STATUS_SUCCESS upon successful registration, 281 * QDF_STATUS_E_FAILURE upon failure 282 */ 283 static QDF_STATUS 284 wlan_spectral_psoc_target_attach(struct wlan_objmgr_psoc *psoc) 285 { 286 struct spectral_context *sc = NULL; 287 288 if (!psoc) { 289 spectral_err("psoc is null"); 290 return QDF_STATUS_E_FAILURE; 291 } 292 293 sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 294 WLAN_UMAC_COMP_SPECTRAL); 295 if (!sc) { 296 spectral_err("Spectral context is null"); 297 return QDF_STATUS_E_NOMEM; 298 } 299 300 if (sc->sptrlc_psoc_spectral_init) { 301 void *target_handle; 302 303 target_handle = sc->sptrlc_psoc_spectral_init(psoc); 304 if (!target_handle) { 305 spectral_err("Spectral psoc lmac object is NULL!"); 306 return QDF_STATUS_E_FAILURE; 307 } 308 sc->psoc_target_handle = target_handle; 309 } 310 311 return QDF_STATUS_SUCCESS; 312 } 313 314 /** 315 * wlan_spectral_psoc_target_detach() - Spectral psoc target detach 316 * @psoc: pointer to psoc object 317 * 318 * API to destroy Spectral psoc target object 319 * 320 * Return: QDF_STATUS_SUCCESS upon successful registration, 321 * QDF_STATUS_E_FAILURE upon failure 322 */ 323 static QDF_STATUS 324 wlan_spectral_psoc_target_detach(struct wlan_objmgr_psoc *psoc) 325 { 326 struct spectral_context *sc = NULL; 327 328 if (!psoc) { 329 spectral_err("psoc is null"); 330 return QDF_STATUS_E_FAILURE; 331 } 332 333 sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 334 WLAN_UMAC_COMP_SPECTRAL); 335 if (!sc) { 336 spectral_err("Spectral context is null"); 337 return QDF_STATUS_E_INVAL; 338 } 339 340 if (sc->sptrlc_psoc_spectral_deinit) 341 sc->sptrlc_psoc_spectral_deinit(psoc); 342 sc->psoc_target_handle = NULL; 343 344 return QDF_STATUS_SUCCESS; 345 } 346 347 #ifdef DIRECT_BUF_RX_ENABLE 348 bool spectral_dbr_event_handler(struct wlan_objmgr_pdev *pdev, 349 struct direct_buf_rx_data *payload) 350 { 351 struct spectral_context *sc; 352 353 if (!pdev) { 354 spectral_err("PDEV is NULL!"); 355 return -EINVAL; 356 } 357 sc = spectral_get_spectral_ctx_from_pdev(pdev); 358 if (!sc) { 359 spectral_err("spectral context is NULL!"); 360 return -EINVAL; 361 } 362 363 sc->sptrlc_process_spectral_report(pdev, payload); 364 365 return true; 366 } 367 #endif 368 369 QDF_STATUS spectral_pdev_open(struct wlan_objmgr_pdev *pdev) 370 { 371 struct wlan_objmgr_psoc *psoc; 372 QDF_STATUS status; 373 374 psoc = wlan_pdev_get_psoc(pdev); 375 376 if (wlan_spectral_is_feature_disabled(psoc)) { 377 spectral_info("Spectral is disabled"); 378 return QDF_STATUS_COMP_DISABLED; 379 } 380 381 if (cfg_get(psoc, CFG_SPECTRAL_POISON_BUFS)) 382 tgt_set_spectral_dma_debug(pdev, SPECTRAL_DMA_BUFFER_DEBUG, 1); 383 384 status = tgt_spectral_register_to_dbr(pdev); 385 return QDF_STATUS_SUCCESS; 386 } 387 388 QDF_STATUS spectral_register_dbr(struct wlan_objmgr_pdev *pdev) 389 { 390 return tgt_spectral_register_to_dbr(pdev); 391 } 392 393 qdf_export_symbol(spectral_register_dbr); 394 395 QDF_STATUS spectral_unregister_dbr(struct wlan_objmgr_pdev *pdev) 396 { 397 QDF_STATUS status; 398 399 status = tgt_spectral_unregister_to_dbr(pdev); 400 401 return status; 402 } 403 404 qdf_export_symbol(spectral_unregister_dbr); 405 406 QDF_STATUS wlan_spectral_psoc_open(struct wlan_objmgr_psoc *psoc) 407 { 408 if (!psoc) { 409 spectral_err("psoc is null"); 410 return QDF_STATUS_E_INVAL; 411 } 412 413 if (wlan_spectral_is_feature_disabled(psoc)) { 414 spectral_info("Spectral is disabled"); 415 return QDF_STATUS_COMP_DISABLED; 416 } 417 418 return wlan_spectral_psoc_target_attach(psoc); 419 } 420 421 QDF_STATUS wlan_spectral_psoc_close(struct wlan_objmgr_psoc *psoc) 422 { 423 if (!psoc) { 424 spectral_err("psoc is null"); 425 return QDF_STATUS_E_INVAL; 426 } 427 428 if (wlan_spectral_is_feature_disabled(psoc)) { 429 spectral_info("Spectral is disabled"); 430 return QDF_STATUS_COMP_DISABLED; 431 } 432 433 return wlan_spectral_psoc_target_detach(psoc); 434 } 435 436 QDF_STATUS wlan_spectral_psoc_enable(struct wlan_objmgr_psoc *psoc) 437 { 438 if (!psoc) { 439 spectral_err("psoc is null"); 440 return QDF_STATUS_E_INVAL; 441 } 442 443 if (wlan_spectral_is_feature_disabled(psoc)) { 444 spectral_info("Spectral is disabled"); 445 return QDF_STATUS_COMP_DISABLED; 446 } 447 448 return tgt_spectral_register_events(psoc); 449 } 450 451 QDF_STATUS wlan_spectral_psoc_disable(struct wlan_objmgr_psoc *psoc) 452 { 453 if (!psoc) { 454 spectral_err("psoc is null"); 455 return QDF_STATUS_E_INVAL; 456 } 457 458 if (wlan_spectral_is_feature_disabled(psoc)) { 459 spectral_info("Spectral is disabled"); 460 return QDF_STATUS_COMP_DISABLED; 461 } 462 463 return tgt_spectral_unregister_events(psoc); 464 } 465