spectral_common.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. /*
  2. * Copyright (c) 2011,2017 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. #include "spectral_cmn_api_i.h"
  20. #include "spectral_da_api_i.h"
  21. #include "spectral_ol_api_i.h"
  22. #include <qdf_mem.h>
  23. #include <qdf_types.h>
  24. #ifdef CONFIG_WIN
  25. #include <osif_private.h>
  26. #include <wlan_mlme_dispatcher.h>
  27. #endif /*CONFIG_WIN*/
  28. #include <wlan_spectral_public_structs.h>
  29. #include <wlan_cfg80211_spectral.h>
  30. /**
  31. * spectral_get_vdev() - Get pointer to vdev to be used for Spectral
  32. * operations
  33. * @pdev: Pointer to pdev
  34. *
  35. * Spectral operates on pdev. However, in order to retrieve some WLAN
  36. * properties, a vdev is required. To facilitate this, the function returns the
  37. * first vdev in our pdev. The caller should release the reference to the vdev
  38. * once it is done using it. Additionally, the caller should ensure it has a
  39. * reference to the pdev at the time of calling this function, and should
  40. * release the pdev reference either after this function returns or at a later
  41. * time when the caller is done using pdev.
  42. * TODO:
  43. * - If the framework later provides an API to obtain the first active
  44. * vdev, then it would be preferable to use this API.
  45. * - Use a common get_vdev() handler for core and target_if using Rx ops. This
  46. * is deferred till details emerge on framework providing API to get first
  47. * active vdev.
  48. *
  49. * Return: Pointer to vdev on success, NULL on failure
  50. */
  51. static struct wlan_objmgr_vdev*
  52. spectral_get_vdev(struct wlan_objmgr_pdev *pdev)
  53. {
  54. struct wlan_objmgr_vdev *vdev = NULL;
  55. qdf_assert_always(pdev);
  56. vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, 0, WLAN_SPECTRAL_ID);
  57. if (!vdev) {
  58. qdf_print("%s: Unable to get first vdev of pdev.\n", __func__);
  59. return NULL;
  60. }
  61. return vdev;
  62. }
  63. #ifndef CONFIG_MCL
  64. static void spectral_register_cfg80211_handlers(struct wlan_objmgr_pdev *pdev)
  65. {
  66. wlan_cfg80211_register_spectral_cmd_handler(
  67. pdev,
  68. SPECTRAL_SCAN_START_HANDLER_IDX,
  69. wlan_cfg80211_spectral_scan_config_and_start);
  70. wlan_cfg80211_register_spectral_cmd_handler(
  71. pdev,
  72. SPECTRAL_SCAN_STOP_HANDLER_IDX,
  73. wlan_cfg80211_spectral_scan_stop);
  74. wlan_cfg80211_register_spectral_cmd_handler(
  75. pdev,
  76. SPECTRAL_SCAN_GET_CONFIG_HANDLER_IDX,
  77. wlan_cfg80211_spectral_scan_get_config);
  78. wlan_cfg80211_register_spectral_cmd_handler(
  79. pdev,
  80. SPECTRAL_SCAN_GET_DIAG_STATS_HANDLER_IDX,
  81. wlan_cfg80211_spectral_scan_get_diag_stats);
  82. wlan_cfg80211_register_spectral_cmd_handler(
  83. pdev,
  84. SPECTRAL_SCAN_GET_CAP_HANDLER_IDX,
  85. wlan_cfg80211_spectral_scan_get_cap);
  86. wlan_cfg80211_register_spectral_cmd_handler(
  87. pdev,
  88. SPECTRAL_SCAN_GET_STATUS_HANDLER_IDX,
  89. wlan_cfg80211_spectral_scan_get_status);
  90. }
  91. #else
  92. static void spectral_register_cfg80211_handlers(struct wlan_objmgr_pdev *pdev)
  93. {
  94. }
  95. #endif
  96. int spectral_control_cmn(
  97. struct wlan_objmgr_pdev *pdev,
  98. u_int id,
  99. void *indata,
  100. u_int32_t insize,
  101. void *outdata, u_int32_t *outsize)
  102. {
  103. int error = 0;
  104. int temp_debug;
  105. struct spectral_config sp_out;
  106. struct spectral_config *sp_in;
  107. struct spectral_config *spectralparams;
  108. struct spectral_context *sc;
  109. struct wlan_objmgr_vdev *vdev = NULL;
  110. u_int8_t vdev_rxchainmask = 0;
  111. if (!pdev) {
  112. spectral_err("PDEV is NULL!\n");
  113. error = -EINVAL;
  114. goto bad;
  115. }
  116. sc = spectral_get_spectral_ctx_from_pdev(pdev);
  117. if (!sc) {
  118. spectral_err("atf context is NULL!\n");
  119. error = -EINVAL;
  120. goto bad;
  121. }
  122. switch (id) {
  123. case SPECTRAL_SET_CONFIG:
  124. {
  125. if (insize < sizeof(struct spectral_config) || !indata) {
  126. error = -EINVAL;
  127. break;
  128. }
  129. sp_in = (struct spectral_config *)indata;
  130. if (sp_in->ss_count != SPECTRAL_PHYERR_PARAM_NOVAL) {
  131. if (!sc->sptrlc_set_spectral_config(
  132. pdev,
  133. SPECTRAL_PARAM_SCAN_COUNT,
  134. sp_in->ss_count))
  135. error = -EINVAL;
  136. }
  137. if (sp_in->ss_fft_period != SPECTRAL_PHYERR_PARAM_NOVAL) {
  138. if (!sc->sptrlc_set_spectral_config(
  139. pdev,
  140. SPECTRAL_PARAM_FFT_PERIOD,
  141. sp_in->ss_fft_period))
  142. error = -EINVAL;
  143. }
  144. if (sp_in->ss_period != SPECTRAL_PHYERR_PARAM_NOVAL) {
  145. if (!sc->sptrlc_set_spectral_config(
  146. pdev,
  147. SPECTRAL_PARAM_SCAN_PERIOD,
  148. sp_in->ss_period))
  149. error = -EINVAL;
  150. }
  151. if (sp_in->ss_short_report != SPECTRAL_PHYERR_PARAM_NOVAL) {
  152. if (!sc->sptrlc_set_spectral_config(
  153. pdev,
  154. SPECTRAL_PARAM_SHORT_REPORT,
  155. (u_int32_t)(sp_in->ss_short_report ? 1 : 0)))
  156. error = -EINVAL;
  157. }
  158. if (sp_in->ss_spectral_pri != SPECTRAL_PHYERR_PARAM_NOVAL) {
  159. if (!sc->sptrlc_set_spectral_config(
  160. pdev,
  161. SPECTRAL_PARAM_SPECT_PRI,
  162. (u_int32_t)(sp_in->ss_spectral_pri)))
  163. error = -EINVAL;
  164. }
  165. if (sp_in->ss_fft_size != SPECTRAL_PHYERR_PARAM_NOVAL) {
  166. if (!sc->sptrlc_set_spectral_config(
  167. pdev,
  168. SPECTRAL_PARAM_FFT_SIZE,
  169. sp_in->ss_fft_size))
  170. error = -EINVAL;
  171. }
  172. if (sp_in->ss_gc_ena != SPECTRAL_PHYERR_PARAM_NOVAL) {
  173. if (!sc->sptrlc_set_spectral_config(
  174. pdev,
  175. SPECTRAL_PARAM_GC_ENA,
  176. sp_in->ss_gc_ena))
  177. error = -EINVAL;
  178. }
  179. if (sp_in->ss_restart_ena != SPECTRAL_PHYERR_PARAM_NOVAL) {
  180. if (!sc->sptrlc_set_spectral_config(
  181. pdev,
  182. SPECTRAL_PARAM_RESTART_ENA,
  183. sp_in->ss_restart_ena))
  184. error = -EINVAL;
  185. }
  186. if (sp_in->ss_noise_floor_ref != SPECTRAL_PHYERR_PARAM_NOVAL) {
  187. if (!sc->sptrlc_set_spectral_config(
  188. pdev,
  189. SPECTRAL_PARAM_NOISE_FLOOR_REF,
  190. sp_in->ss_noise_floor_ref))
  191. error = -EINVAL;
  192. }
  193. if (sp_in->ss_init_delay != SPECTRAL_PHYERR_PARAM_NOVAL) {
  194. if (!sc->sptrlc_set_spectral_config(
  195. pdev,
  196. SPECTRAL_PARAM_INIT_DELAY,
  197. sp_in->ss_init_delay))
  198. error = -EINVAL;
  199. }
  200. if (sp_in->ss_nb_tone_thr != SPECTRAL_PHYERR_PARAM_NOVAL) {
  201. if (!sc->sptrlc_set_spectral_config(
  202. pdev,
  203. SPECTRAL_PARAM_NB_TONE_THR,
  204. sp_in->ss_nb_tone_thr))
  205. error = -EINVAL;
  206. }
  207. if (sp_in->ss_str_bin_thr != SPECTRAL_PHYERR_PARAM_NOVAL) {
  208. if (!sc->sptrlc_set_spectral_config(
  209. pdev,
  210. SPECTRAL_PARAM_STR_BIN_THR,
  211. sp_in->ss_str_bin_thr))
  212. error = -EINVAL;
  213. }
  214. if (sp_in->ss_wb_rpt_mode != SPECTRAL_PHYERR_PARAM_NOVAL) {
  215. if (!sc->sptrlc_set_spectral_config(
  216. pdev,
  217. SPECTRAL_PARAM_WB_RPT_MODE,
  218. sp_in->ss_wb_rpt_mode))
  219. error = -EINVAL;
  220. }
  221. if (sp_in->ss_rssi_rpt_mode != SPECTRAL_PHYERR_PARAM_NOVAL) {
  222. if (!sc->sptrlc_set_spectral_config(
  223. pdev,
  224. SPECTRAL_PARAM_RSSI_RPT_MODE,
  225. sp_in->ss_rssi_rpt_mode))
  226. error = -EINVAL;
  227. }
  228. if (sp_in->ss_rssi_thr != SPECTRAL_PHYERR_PARAM_NOVAL) {
  229. if (!sc->sptrlc_set_spectral_config(
  230. pdev,
  231. SPECTRAL_PARAM_RSSI_THR,
  232. sp_in->ss_rssi_thr))
  233. error = -EINVAL;
  234. }
  235. if (sp_in->ss_pwr_format != SPECTRAL_PHYERR_PARAM_NOVAL) {
  236. if (!sc->sptrlc_set_spectral_config(
  237. pdev,
  238. SPECTRAL_PARAM_PWR_FORMAT,
  239. sp_in->ss_pwr_format))
  240. error = -EINVAL;
  241. }
  242. if (sp_in->ss_rpt_mode != SPECTRAL_PHYERR_PARAM_NOVAL) {
  243. if (!sc->sptrlc_set_spectral_config(
  244. pdev,
  245. SPECTRAL_PARAM_RPT_MODE,
  246. sp_in->ss_rpt_mode))
  247. error = -EINVAL;
  248. }
  249. if (sp_in->ss_bin_scale != SPECTRAL_PHYERR_PARAM_NOVAL) {
  250. if (!sc->sptrlc_set_spectral_config(
  251. pdev,
  252. SPECTRAL_PARAM_BIN_SCALE,
  253. sp_in->ss_bin_scale))
  254. error = -EINVAL;
  255. }
  256. if (sp_in->ss_dbm_adj != SPECTRAL_PHYERR_PARAM_NOVAL) {
  257. if (!sc->sptrlc_set_spectral_config(
  258. pdev,
  259. SPECTRAL_PARAM_DBM_ADJ,
  260. sp_in->ss_dbm_adj))
  261. error = -EINVAL;
  262. }
  263. if (sp_in->ss_chn_mask != SPECTRAL_PHYERR_PARAM_NOVAL) {
  264. /* Check if any of the inactive Rx antenna chains is
  265. * set active in
  266. * spectral chainmask
  267. */
  268. vdev = spectral_get_vdev(pdev);
  269. if (!vdev) {
  270. error = -ENOENT;
  271. break;
  272. }
  273. vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev);
  274. wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
  275. if (!(sp_in->ss_chn_mask & vdev_rxchainmask)) {
  276. qdf_print("Invalid Spectral Chainmask - "
  277. "Inactive Rx antenna chain cannot "
  278. "be an active spectral chain\n");
  279. error = -EINVAL;
  280. break;
  281. } else if (!sc->sptrlc_set_spectral_config(pdev,
  282. SPECTRAL_PARAM_CHN_MASK, sp_in->ss_chn_mask)) {
  283. error = -EINVAL;
  284. }
  285. }
  286. }
  287. break;
  288. case SPECTRAL_GET_CONFIG:
  289. {
  290. if (!outdata || !outsize || (*outsize < sizeof(
  291. struct spectral_config))) {
  292. error = -EINVAL;
  293. break;
  294. }
  295. *outsize = sizeof(struct spectral_config);
  296. sc->sptrlc_get_spectral_config(pdev, &sp_out);
  297. spectralparams = (struct spectral_config *)outdata;
  298. spectralparams->ss_fft_period = sp_out.ss_fft_period;
  299. spectralparams->ss_period = sp_out.ss_period;
  300. spectralparams->ss_count = sp_out.ss_count;
  301. spectralparams->ss_short_report = sp_out.ss_short_report;
  302. spectralparams->ss_spectral_pri = sp_out.ss_spectral_pri;
  303. spectralparams->ss_fft_size = sp_out.ss_fft_size;
  304. spectralparams->ss_gc_ena = sp_out.ss_gc_ena;
  305. spectralparams->ss_restart_ena = sp_out.ss_restart_ena;
  306. spectralparams->ss_noise_floor_ref = sp_out.ss_noise_floor_ref;
  307. spectralparams->ss_init_delay = sp_out.ss_init_delay;
  308. spectralparams->ss_nb_tone_thr = sp_out.ss_nb_tone_thr;
  309. spectralparams->ss_str_bin_thr = sp_out.ss_str_bin_thr;
  310. spectralparams->ss_wb_rpt_mode = sp_out.ss_wb_rpt_mode;
  311. spectralparams->ss_rssi_rpt_mode = sp_out.ss_rssi_rpt_mode;
  312. spectralparams->ss_rssi_thr = sp_out.ss_rssi_thr;
  313. spectralparams->ss_pwr_format = sp_out.ss_pwr_format;
  314. spectralparams->ss_rpt_mode = sp_out.ss_rpt_mode;
  315. spectralparams->ss_bin_scale = sp_out.ss_bin_scale;
  316. spectralparams->ss_dbm_adj = sp_out.ss_dbm_adj;
  317. spectralparams->ss_chn_mask = sp_out.ss_chn_mask;
  318. }
  319. break;
  320. case SPECTRAL_IS_ACTIVE:
  321. {
  322. if (!outdata || !outsize || *outsize < sizeof(u_int32_t)) {
  323. error = -EINVAL;
  324. break;
  325. }
  326. *outsize = sizeof(u_int32_t);
  327. *((u_int32_t *)outdata) =
  328. (u_int32_t)sc->sptrlc_is_spectral_active(pdev);
  329. }
  330. break;
  331. case SPECTRAL_IS_ENABLED:
  332. {
  333. if (!outdata || !outsize || *outsize < sizeof(u_int32_t)) {
  334. error = -EINVAL;
  335. break;
  336. }
  337. *outsize = sizeof(u_int32_t);
  338. *((u_int32_t *)outdata) =
  339. (u_int32_t)sc->sptrlc_is_spectral_enabled(pdev);
  340. }
  341. break;
  342. case SPECTRAL_SET_DEBUG_LEVEL:
  343. {
  344. if (insize < sizeof(u_int32_t) || !indata) {
  345. error = -EINVAL;
  346. break;
  347. }
  348. temp_debug = *(u_int32_t *)indata;
  349. sc->sptrlc_set_debug_level(pdev, temp_debug);
  350. }
  351. break;
  352. case SPECTRAL_GET_DEBUG_LEVEL:
  353. {
  354. if (!outdata || !outsize || *outsize < sizeof(u_int32_t)) {
  355. error = -EINVAL;
  356. break;
  357. }
  358. *outsize = sizeof(u_int32_t);
  359. *((u_int32_t *)outdata) =
  360. (u_int32_t)sc->sptrlc_get_debug_level(pdev);
  361. }
  362. break;
  363. case SPECTRAL_ACTIVATE_SCAN:
  364. {
  365. sc->sptrlc_start_spectral_scan(pdev);
  366. }
  367. break;
  368. case SPECTRAL_STOP_SCAN:
  369. {
  370. sc->sptrlc_stop_spectral_scan(pdev);
  371. }
  372. break;
  373. case SPECTRAL_GET_CAPABILITY_INFO:
  374. {
  375. if (!outdata || !outsize ||
  376. *outsize < sizeof(struct spectral_caps)) {
  377. error = -EINVAL;
  378. break;
  379. }
  380. *outsize = sizeof(struct spectral_caps);
  381. sc->sptrlc_get_spectral_capinfo(pdev, outdata);
  382. }
  383. break;
  384. case SPECTRAL_GET_DIAG_STATS:
  385. {
  386. if (!outdata || !outsize ||
  387. (*outsize < sizeof(struct spectral_diag_stats))) {
  388. error = -EINVAL;
  389. break;
  390. }
  391. *outsize = sizeof(struct spectral_diag_stats);
  392. sc->sptrlc_get_spectral_diagstats(pdev, outdata);
  393. }
  394. break;
  395. case SPECTRAL_GET_CHAN_WIDTH:
  396. {
  397. u_int32_t chan_width;
  398. vdev = spectral_get_vdev(pdev);
  399. if (!vdev)
  400. return -ENOENT;
  401. chan_width = spectral_vdev_get_ch_width(vdev);
  402. wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
  403. if (!outdata || !outsize ||
  404. *outsize < sizeof(chan_width)) {
  405. error = -EINVAL;
  406. break;
  407. }
  408. *outsize = sizeof(chan_width);
  409. *((u_int32_t *)outdata) = (u_int32_t)chan_width;
  410. }
  411. break;
  412. default:
  413. error = -EINVAL;
  414. break;
  415. }
  416. bad:
  417. return error;
  418. }
  419. static void spectral_ctx_deinit(struct spectral_context *sc)
  420. {
  421. if (sc) {
  422. sc->sptrlc_ucfg_phyerr_config = NULL;
  423. sc->sptrlc_pdev_spectral_init = NULL;
  424. sc->sptrlc_pdev_spectral_deinit = NULL;
  425. sc->sptrlc_set_spectral_config = NULL;
  426. sc->sptrlc_get_spectral_config = NULL;
  427. sc->sptrlc_start_spectral_scan = NULL;
  428. sc->sptrlc_stop_spectral_scan = NULL;
  429. sc->sptrlc_is_spectral_active = NULL;
  430. sc->sptrlc_is_spectral_enabled = NULL;
  431. sc->sptrlc_set_debug_level = NULL;
  432. sc->sptrlc_get_debug_level = NULL;
  433. sc->sptrlc_get_spectral_capinfo = NULL;
  434. sc->sptrlc_get_spectral_diagstats = NULL;
  435. }
  436. }
  437. QDF_STATUS
  438. wlan_spectral_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc, void *arg)
  439. {
  440. struct spectral_context *sc = NULL;
  441. if (!psoc) {
  442. spectral_err("PSOC is NULL\n");
  443. return QDF_STATUS_E_FAILURE;
  444. }
  445. sc = (struct spectral_context *)qdf_mem_malloc(
  446. sizeof(struct spectral_context));
  447. if (!sc) {
  448. spectral_err("Failed to allocate spectral_ctx object\n");
  449. return QDF_STATUS_E_NOMEM;
  450. }
  451. qdf_mem_zero(sc, sizeof(struct spectral_context));
  452. sc->psoc_obj = psoc;
  453. if (wlan_objmgr_psoc_get_dev_type(psoc) == WLAN_DEV_OL)
  454. spectral_ctx_init_ol(sc);
  455. #ifdef CONFIG_WIN
  456. else if (wlan_objmgr_psoc_get_dev_type(psoc) == WLAN_DEV_DA)
  457. spectral_ctx_init_da(sc);
  458. #endif
  459. wlan_objmgr_psoc_component_obj_attach(psoc, WLAN_UMAC_COMP_SPECTRAL,
  460. (void *)sc, QDF_STATUS_SUCCESS);
  461. return QDF_STATUS_SUCCESS;
  462. }
  463. QDF_STATUS wlan_spectral_psoc_obj_destroy_handler(
  464. struct wlan_objmgr_psoc *psoc,
  465. void *arg)
  466. {
  467. struct spectral_context *sc = NULL;
  468. if (!psoc) {
  469. spectral_err("PSOC is NULL\n");
  470. return QDF_STATUS_E_FAILURE;
  471. }
  472. sc = wlan_objmgr_psoc_get_comp_private_obj(
  473. psoc,
  474. WLAN_UMAC_COMP_SPECTRAL);
  475. if (sc) {
  476. wlan_objmgr_psoc_component_obj_detach(
  477. psoc,
  478. WLAN_UMAC_COMP_SPECTRAL,
  479. (void *)sc);
  480. /* Deinitilise function pointers from spectral context */
  481. spectral_ctx_deinit(sc);
  482. qdf_mem_free(sc);
  483. }
  484. return QDF_STATUS_SUCCESS;
  485. }
  486. QDF_STATUS
  487. wlan_spectral_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg)
  488. {
  489. struct pdev_spectral *ps = NULL;
  490. struct spectral_context *sc = NULL;
  491. void *target_handle = NULL;
  492. if (!pdev) {
  493. spectral_err("PDEV is NULL\n");
  494. return QDF_STATUS_E_FAILURE;
  495. }
  496. ps = (struct pdev_spectral *)qdf_mem_malloc(
  497. sizeof(struct pdev_spectral));
  498. if (!ps) {
  499. spectral_err("Failed to allocate pdev_spectral object\n");
  500. return QDF_STATUS_E_NOMEM;
  501. }
  502. sc = spectral_get_spectral_ctx_from_pdev(pdev);
  503. if (!sc) {
  504. spectral_err("Spectral context is NULL!\n");
  505. goto cleanup;
  506. }
  507. qdf_mem_zero(ps, sizeof(struct pdev_spectral));
  508. ps->psptrl_pdev = pdev;
  509. spectral_register_cfg80211_handlers(pdev);
  510. if (sc->sptrlc_pdev_spectral_init) {
  511. target_handle = sc->sptrlc_pdev_spectral_init(pdev);
  512. if (!target_handle) {
  513. spectral_err("Spectral lmac object is NULL!\n");
  514. goto cleanup;
  515. }
  516. ps->psptrl_target_handle = target_handle;
  517. }
  518. wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_UMAC_COMP_SPECTRAL,
  519. (void *)ps, QDF_STATUS_SUCCESS);
  520. return QDF_STATUS_SUCCESS;
  521. cleanup:
  522. qdf_mem_free(ps);
  523. return QDF_STATUS_E_FAILURE;
  524. }
  525. QDF_STATUS
  526. wlan_spectral_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev, void *arg)
  527. {
  528. struct pdev_spectral *ps = NULL;
  529. struct spectral_context *sc = NULL;
  530. if (!pdev) {
  531. spectral_err("PDEV is NULL\n");
  532. return QDF_STATUS_E_FAILURE;
  533. }
  534. sc = spectral_get_spectral_ctx_from_pdev(pdev);
  535. if (!sc) {
  536. spectral_err("Spectral context is NULL!\n");
  537. return QDF_STATUS_E_FAILURE;
  538. }
  539. ps = wlan_objmgr_pdev_get_comp_private_obj(
  540. pdev,
  541. WLAN_UMAC_COMP_SPECTRAL);
  542. if (ps) {
  543. if (sc->sptrlc_pdev_spectral_deinit)
  544. sc->sptrlc_pdev_spectral_deinit(pdev);
  545. ps->psptrl_target_handle = NULL;
  546. wlan_objmgr_pdev_component_obj_detach(
  547. pdev,
  548. WLAN_UMAC_COMP_SPECTRAL,
  549. (void *)ps);
  550. qdf_mem_free(ps);
  551. }
  552. return QDF_STATUS_SUCCESS;
  553. }