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 return sc->legacy_cbacks.vdev_get_chan_freq(vdev); 144 } 145 146 int16_t 147 spectral_vdev_get_chan_freq_seg2(struct wlan_objmgr_vdev *vdev) 148 { 149 struct spectral_context *sc; 150 151 sc = spectral_get_spectral_ctx_from_vdev(vdev); 152 if (!sc) { 153 spectral_err("spectral context is null"); 154 return -EINVAL; 155 } 156 157 return sc->legacy_cbacks.vdev_get_chan_freq_seg2(vdev); 158 } 159 160 enum phy_ch_width 161 spectral_vdev_get_ch_width(struct wlan_objmgr_vdev *vdev) 162 { 163 struct spectral_context *sc; 164 165 sc = spectral_get_spectral_ctx_from_vdev(vdev); 166 if (!sc) { 167 spectral_err("spectral context is Null"); 168 return CH_WIDTH_INVALID; 169 } 170 171 return sc->legacy_cbacks.vdev_get_ch_width(vdev); 172 } 173 174 int 175 spectral_vdev_get_sec20chan_freq_mhz(struct wlan_objmgr_vdev *vdev, 176 uint16_t *sec20chan_freq) 177 { 178 struct spectral_context *sc; 179 180 sc = spectral_get_spectral_ctx_from_vdev(vdev); 181 if (!sc) { 182 spectral_err("spectral context is Null"); 183 return -EINVAL; 184 } 185 186 return sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz(vdev, 187 sec20chan_freq); 188 } 189 190 void 191 wlan_lmac_if_sptrl_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 192 { 193 struct wlan_lmac_if_sptrl_rx_ops *sptrl_rx_ops = &rx_ops->sptrl_rx_ops; 194 195 /* Spectral rx ops */ 196 sptrl_rx_ops->sptrlro_get_pdev_target_handle = 197 tgt_get_pdev_target_handle; 198 sptrl_rx_ops->sptrlro_get_psoc_target_handle = 199 tgt_get_psoc_target_handle; 200 sptrl_rx_ops->sptrlro_vdev_get_chan_freq = spectral_vdev_get_chan_freq; 201 sptrl_rx_ops->sptrlro_vdev_get_chan_freq_seg2 = 202 spectral_vdev_get_chan_freq_seg2; 203 sptrl_rx_ops->sptrlro_vdev_get_ch_width = spectral_vdev_get_ch_width; 204 sptrl_rx_ops->sptrlro_vdev_get_sec20chan_freq_mhz = 205 spectral_vdev_get_sec20chan_freq_mhz; 206 sptrl_rx_ops->sptrlro_spectral_is_feature_disabled = 207 wlan_spectral_is_feature_disabled; 208 } 209 210 QDF_STATUS 211 wlan_register_spectral_wmi_ops(struct wlan_objmgr_psoc *psoc, 212 struct spectral_wmi_ops *wmi_ops) 213 { 214 struct spectral_context *sc; 215 216 if (!psoc) { 217 spectral_err("psoc is NULL!"); 218 return QDF_STATUS_E_INVAL; 219 } 220 221 sc = spectral_get_spectral_ctx_from_psoc(psoc); 222 if (!sc) { 223 spectral_err("spectral context is NULL!"); 224 return QDF_STATUS_E_FAILURE; 225 } 226 227 return sc->sptrlc_register_spectral_wmi_ops(psoc, wmi_ops); 228 } 229 230 qdf_export_symbol(wlan_register_spectral_wmi_ops); 231 232 QDF_STATUS 233 wlan_register_spectral_tgt_ops(struct wlan_objmgr_psoc *psoc, 234 struct spectral_tgt_ops *tgt_ops) 235 { 236 struct spectral_context *sc; 237 238 if (!psoc) { 239 spectral_err("psoc is NULL!"); 240 return QDF_STATUS_E_INVAL; 241 } 242 243 sc = spectral_get_spectral_ctx_from_psoc(psoc); 244 if (!sc) { 245 spectral_err("spectral context is NULL!"); 246 return QDF_STATUS_E_FAILURE; 247 } 248 249 return sc->sptrlc_register_spectral_tgt_ops(psoc, tgt_ops); 250 } 251 252 qdf_export_symbol(wlan_register_spectral_tgt_ops); 253 254 /** 255 * wlan_spectral_psoc_target_attach() - Spectral psoc target attach 256 * @psoc: pointer to psoc object 257 * 258 * API to initialize Spectral psoc target object 259 * 260 * Return: QDF_STATUS_SUCCESS upon successful registration, 261 * QDF_STATUS_E_FAILURE upon failure 262 */ 263 static QDF_STATUS 264 wlan_spectral_psoc_target_attach(struct wlan_objmgr_psoc *psoc) 265 { 266 struct spectral_context *sc = NULL; 267 268 if (!psoc) { 269 spectral_err("psoc is null"); 270 return QDF_STATUS_E_FAILURE; 271 } 272 273 sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 274 WLAN_UMAC_COMP_SPECTRAL); 275 if (!sc) { 276 spectral_err("Spectral context is null"); 277 return QDF_STATUS_E_NOMEM; 278 } 279 280 if (sc->sptrlc_psoc_spectral_init) { 281 void *target_handle; 282 283 target_handle = sc->sptrlc_psoc_spectral_init(psoc); 284 if (!target_handle) { 285 spectral_err("Spectral psoc lmac object is NULL!"); 286 return QDF_STATUS_E_FAILURE; 287 } 288 sc->psoc_target_handle = target_handle; 289 } 290 291 return QDF_STATUS_SUCCESS; 292 } 293 294 /** 295 * wlan_spectral_psoc_target_detach() - Spectral psoc target detach 296 * @psoc: pointer to psoc object 297 * 298 * API to destroy Spectral psoc target object 299 * 300 * Return: QDF_STATUS_SUCCESS upon successful registration, 301 * QDF_STATUS_E_FAILURE upon failure 302 */ 303 static QDF_STATUS 304 wlan_spectral_psoc_target_detach(struct wlan_objmgr_psoc *psoc) 305 { 306 struct spectral_context *sc = NULL; 307 308 if (!psoc) { 309 spectral_err("psoc is null"); 310 return QDF_STATUS_E_FAILURE; 311 } 312 313 sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 314 WLAN_UMAC_COMP_SPECTRAL); 315 if (!sc) { 316 spectral_err("Spectral context is null"); 317 return QDF_STATUS_E_INVAL; 318 } 319 320 if (sc->sptrlc_psoc_spectral_deinit) 321 sc->sptrlc_psoc_spectral_deinit(psoc); 322 sc->psoc_target_handle = NULL; 323 324 return QDF_STATUS_SUCCESS; 325 } 326 327 #ifdef DIRECT_BUF_RX_ENABLE 328 bool spectral_dbr_event_handler(struct wlan_objmgr_pdev *pdev, 329 struct direct_buf_rx_data *payload) 330 { 331 struct spectral_context *sc; 332 333 if (!pdev) { 334 spectral_err("PDEV is NULL!"); 335 return -EINVAL; 336 } 337 sc = spectral_get_spectral_ctx_from_pdev(pdev); 338 if (!sc) { 339 spectral_err("spectral context is NULL!"); 340 return -EINVAL; 341 } 342 343 sc->sptrlc_process_spectral_report(pdev, payload); 344 345 return true; 346 } 347 #endif 348 349 QDF_STATUS spectral_pdev_open(struct wlan_objmgr_pdev *pdev) 350 { 351 struct wlan_objmgr_psoc *psoc; 352 QDF_STATUS status; 353 354 psoc = wlan_pdev_get_psoc(pdev); 355 356 if (wlan_spectral_is_feature_disabled(psoc)) { 357 spectral_info("Spectral is disabled"); 358 return QDF_STATUS_COMP_DISABLED; 359 } 360 361 if (cfg_get(psoc, CFG_SPECTRAL_POISON_BUFS)) 362 tgt_set_spectral_dma_debug(pdev, SPECTRAL_DMA_BUFFER_DEBUG, 1); 363 364 status = tgt_spectral_register_to_dbr(pdev); 365 return QDF_STATUS_SUCCESS; 366 } 367 368 QDF_STATUS spectral_register_dbr(struct wlan_objmgr_pdev *pdev) 369 { 370 return tgt_spectral_register_to_dbr(pdev); 371 } 372 373 qdf_export_symbol(spectral_register_dbr); 374 375 QDF_STATUS spectral_unregister_dbr(struct wlan_objmgr_pdev *pdev) 376 { 377 QDF_STATUS status; 378 379 status = tgt_spectral_unregister_to_dbr(pdev); 380 381 return status; 382 } 383 384 qdf_export_symbol(spectral_unregister_dbr); 385 386 QDF_STATUS wlan_spectral_psoc_open(struct wlan_objmgr_psoc *psoc) 387 { 388 if (!psoc) { 389 spectral_err("psoc is null"); 390 return QDF_STATUS_E_INVAL; 391 } 392 393 if (wlan_spectral_is_feature_disabled(psoc)) { 394 spectral_info("Spectral is disabled"); 395 return QDF_STATUS_COMP_DISABLED; 396 } 397 398 return wlan_spectral_psoc_target_attach(psoc); 399 } 400 401 QDF_STATUS wlan_spectral_psoc_close(struct wlan_objmgr_psoc *psoc) 402 { 403 if (!psoc) { 404 spectral_err("psoc is null"); 405 return QDF_STATUS_E_INVAL; 406 } 407 408 if (wlan_spectral_is_feature_disabled(psoc)) { 409 spectral_info("Spectral is disabled"); 410 return QDF_STATUS_COMP_DISABLED; 411 } 412 413 return wlan_spectral_psoc_target_detach(psoc); 414 } 415 416 QDF_STATUS wlan_spectral_psoc_enable(struct wlan_objmgr_psoc *psoc) 417 { 418 if (!psoc) { 419 spectral_err("psoc is null"); 420 return QDF_STATUS_E_INVAL; 421 } 422 423 if (wlan_spectral_is_feature_disabled(psoc)) { 424 spectral_info("Spectral is disabled"); 425 return QDF_STATUS_COMP_DISABLED; 426 } 427 428 return tgt_spectral_register_events(psoc); 429 } 430 431 QDF_STATUS wlan_spectral_psoc_disable(struct wlan_objmgr_psoc *psoc) 432 { 433 if (!psoc) { 434 spectral_err("psoc is null"); 435 return QDF_STATUS_E_INVAL; 436 } 437 438 if (wlan_spectral_is_feature_disabled(psoc)) { 439 spectral_info("Spectral is disabled"); 440 return QDF_STATUS_COMP_DISABLED; 441 } 442 443 return tgt_spectral_unregister_events(psoc); 444 } 445