wlan_spectral_utils_api.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. /*
  2. * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
  3. * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  4. *
  5. *
  6. * Permission to use, copy, modify, and/or distribute this software for
  7. * any purpose with or without fee is hereby granted, provided that the
  8. * above copyright notice and this permission notice appear in all
  9. * copies.
  10. *
  11. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  12. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  13. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  14. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  15. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  16. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  17. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  18. * PERFORMANCE OF THIS SOFTWARE.
  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. bool wlan_spectral_is_mode_disabled_pdev(struct wlan_objmgr_pdev *pdev,
  26. enum spectral_scan_mode smode)
  27. {
  28. bool spectral_mode_disable;
  29. if (!pdev) {
  30. spectral_err("pdev is NULL!");
  31. return true;
  32. }
  33. switch (smode) {
  34. case SPECTRAL_SCAN_MODE_NORMAL:
  35. spectral_mode_disable = wlan_pdev_nif_feat_ext_cap_get(
  36. pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS);
  37. break;
  38. case SPECTRAL_SCAN_MODE_AGILE:
  39. spectral_mode_disable = wlan_pdev_nif_feat_ext_cap_get(
  40. pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS) &&
  41. wlan_pdev_nif_feat_ext_cap_get(
  42. pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS) &&
  43. wlan_pdev_nif_feat_ext_cap_get(
  44. pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS) &&
  45. wlan_pdev_nif_feat_ext_cap_get(
  46. pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS);
  47. break;
  48. default:
  49. spectral_err("Invalid Spectral scan mode %d", smode);
  50. spectral_mode_disable = true;
  51. break;
  52. }
  53. return spectral_mode_disable;
  54. }
  55. bool
  56. wlan_spectral_is_feature_disabled_ini(struct wlan_objmgr_psoc *psoc)
  57. {
  58. if (!psoc) {
  59. spectral_err("PSOC is NULL!");
  60. return true;
  61. }
  62. return wlan_psoc_nif_feat_cap_get(psoc,
  63. WLAN_SOC_F_SPECTRAL_INI_DISABLE);
  64. }
  65. bool
  66. wlan_spectral_is_feature_disabled_psoc(struct wlan_objmgr_psoc *psoc)
  67. {
  68. if (!psoc) {
  69. spectral_err("psoc is NULL!");
  70. return true;
  71. }
  72. return wlan_spectral_is_feature_disabled_ini(psoc);
  73. }
  74. bool
  75. wlan_spectral_is_feature_disabled_pdev(struct wlan_objmgr_pdev *pdev)
  76. {
  77. enum spectral_scan_mode smode;
  78. if (!pdev) {
  79. spectral_err("pdev is NULL!");
  80. return true;
  81. }
  82. smode = SPECTRAL_SCAN_MODE_NORMAL;
  83. for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++)
  84. if (!wlan_spectral_is_mode_disabled_pdev(pdev, smode))
  85. return false;
  86. return true;
  87. }
  88. QDF_STATUS
  89. wlan_spectral_init_pdev_feature_caps(struct wlan_objmgr_pdev *pdev)
  90. {
  91. return tgt_spectral_init_pdev_feature_caps(pdev);
  92. }
  93. QDF_STATUS
  94. wlan_spectral_init_psoc_feature_cap(struct wlan_objmgr_psoc *psoc)
  95. {
  96. if (!psoc) {
  97. spectral_err("PSOC is NULL!");
  98. return QDF_STATUS_E_INVAL;
  99. }
  100. if (cfg_get(psoc, CFG_SPECTRAL_DISABLE))
  101. wlan_psoc_nif_feat_cap_set(psoc,
  102. WLAN_SOC_F_SPECTRAL_INI_DISABLE);
  103. else
  104. wlan_psoc_nif_feat_cap_clear(psoc,
  105. WLAN_SOC_F_SPECTRAL_INI_DISABLE);
  106. return QDF_STATUS_SUCCESS;
  107. }
  108. QDF_STATUS
  109. wlan_spectral_init(void)
  110. {
  111. if (wlan_objmgr_register_psoc_create_handler(
  112. WLAN_UMAC_COMP_SPECTRAL,
  113. wlan_spectral_psoc_obj_create_handler,
  114. NULL) !=
  115. QDF_STATUS_SUCCESS) {
  116. return QDF_STATUS_E_FAILURE;
  117. }
  118. if (wlan_objmgr_register_psoc_destroy_handler(
  119. WLAN_UMAC_COMP_SPECTRAL,
  120. wlan_spectral_psoc_obj_destroy_handler,
  121. NULL) !=
  122. QDF_STATUS_SUCCESS) {
  123. return QDF_STATUS_E_FAILURE;
  124. }
  125. if (wlan_objmgr_register_pdev_create_handler(
  126. WLAN_UMAC_COMP_SPECTRAL,
  127. wlan_spectral_pdev_obj_create_handler,
  128. NULL) !=
  129. QDF_STATUS_SUCCESS) {
  130. return QDF_STATUS_E_FAILURE;
  131. }
  132. if (wlan_objmgr_register_pdev_destroy_handler(
  133. WLAN_UMAC_COMP_SPECTRAL,
  134. wlan_spectral_pdev_obj_destroy_handler,
  135. NULL) !=
  136. QDF_STATUS_SUCCESS) {
  137. return QDF_STATUS_E_FAILURE;
  138. }
  139. return QDF_STATUS_SUCCESS;
  140. }
  141. QDF_STATUS
  142. wlan_spectral_deinit(void)
  143. {
  144. if (wlan_objmgr_unregister_psoc_create_handler(
  145. WLAN_UMAC_COMP_SPECTRAL,
  146. wlan_spectral_psoc_obj_create_handler,
  147. NULL) !=
  148. QDF_STATUS_SUCCESS) {
  149. return QDF_STATUS_E_FAILURE;
  150. }
  151. if (wlan_objmgr_unregister_psoc_destroy_handler(
  152. WLAN_UMAC_COMP_SPECTRAL,
  153. wlan_spectral_psoc_obj_destroy_handler,
  154. NULL) !=
  155. QDF_STATUS_SUCCESS) {
  156. return QDF_STATUS_E_FAILURE;
  157. }
  158. if (wlan_objmgr_unregister_pdev_create_handler(
  159. WLAN_UMAC_COMP_SPECTRAL,
  160. wlan_spectral_pdev_obj_create_handler,
  161. NULL) !=
  162. QDF_STATUS_SUCCESS) {
  163. return QDF_STATUS_E_FAILURE;
  164. }
  165. if (wlan_objmgr_unregister_pdev_destroy_handler(
  166. WLAN_UMAC_COMP_SPECTRAL,
  167. wlan_spectral_pdev_obj_destroy_handler,
  168. NULL) !=
  169. QDF_STATUS_SUCCESS) {
  170. return QDF_STATUS_E_FAILURE;
  171. }
  172. return QDF_STATUS_SUCCESS;
  173. }
  174. QDF_STATUS
  175. spectral_register_legacy_cb(struct wlan_objmgr_psoc *psoc,
  176. struct spectral_legacy_cbacks *legacy_cbacks)
  177. {
  178. struct spectral_context *sc;
  179. if (!psoc) {
  180. spectral_err("psoc is null");
  181. return QDF_STATUS_E_INVAL;
  182. }
  183. if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
  184. spectral_info("Spectral feature is disabled");
  185. return QDF_STATUS_COMP_DISABLED;
  186. }
  187. sc = spectral_get_spectral_ctx_from_psoc(psoc);
  188. if (!sc) {
  189. spectral_err("Invalid Context");
  190. return QDF_STATUS_E_FAILURE;
  191. }
  192. sc->legacy_cbacks.vdev_get_chan_freq =
  193. legacy_cbacks->vdev_get_chan_freq;
  194. sc->legacy_cbacks.vdev_get_chan_freq_seg2 =
  195. legacy_cbacks->vdev_get_chan_freq_seg2;
  196. sc->legacy_cbacks.vdev_get_ch_width = legacy_cbacks->vdev_get_ch_width;
  197. sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz =
  198. legacy_cbacks->vdev_get_sec20chan_freq_mhz;
  199. return QDF_STATUS_SUCCESS;
  200. }
  201. qdf_export_symbol(spectral_register_legacy_cb);
  202. int16_t
  203. spectral_vdev_get_chan_freq(struct wlan_objmgr_vdev *vdev)
  204. {
  205. struct spectral_context *sc;
  206. sc = spectral_get_spectral_ctx_from_vdev(vdev);
  207. if (!sc) {
  208. spectral_err("spectral context is Null");
  209. return -EINVAL;
  210. }
  211. if (!sc->legacy_cbacks.vdev_get_chan_freq) {
  212. spectral_err("vdev_get_chan_freq is not supported");
  213. return -ENOTSUPP;
  214. }
  215. return sc->legacy_cbacks.vdev_get_chan_freq(vdev);
  216. }
  217. int16_t
  218. spectral_vdev_get_chan_freq_seg2(struct wlan_objmgr_vdev *vdev)
  219. {
  220. struct spectral_context *sc;
  221. struct wlan_channel *des_chan;
  222. sc = spectral_get_spectral_ctx_from_vdev(vdev);
  223. if (!sc) {
  224. spectral_err("spectral context is null");
  225. return -EINVAL;
  226. }
  227. if (!sc->legacy_cbacks.vdev_get_chan_freq_seg2) {
  228. des_chan = wlan_vdev_mlme_get_des_chan(vdev);
  229. if (des_chan->ch_width == CH_WIDTH_80P80MHZ)
  230. return des_chan->ch_freq_seg2;
  231. else
  232. return 0;
  233. }
  234. return sc->legacy_cbacks.vdev_get_chan_freq_seg2(vdev);
  235. }
  236. enum phy_ch_width
  237. spectral_vdev_get_ch_width(struct wlan_objmgr_vdev *vdev)
  238. {
  239. struct spectral_context *sc;
  240. sc = spectral_get_spectral_ctx_from_vdev(vdev);
  241. if (!sc) {
  242. spectral_err("spectral context is Null");
  243. return CH_WIDTH_INVALID;
  244. }
  245. if (!sc->legacy_cbacks.vdev_get_ch_width) {
  246. spectral_err("vdev_get_ch_width is not supported");
  247. return -ENOTSUPP;
  248. }
  249. return sc->legacy_cbacks.vdev_get_ch_width(vdev);
  250. }
  251. int
  252. spectral_vdev_get_sec20chan_freq_mhz(struct wlan_objmgr_vdev *vdev,
  253. uint16_t *sec20chan_freq)
  254. {
  255. struct spectral_context *sc;
  256. sc = spectral_get_spectral_ctx_from_vdev(vdev);
  257. if (!sc) {
  258. spectral_err("spectral context is Null");
  259. return -EINVAL;
  260. }
  261. if (!sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz) {
  262. spectral_err("vdev_get_sec20chan_freq_mhz is not supported");
  263. return -ENOTSUPP;
  264. }
  265. return sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz(vdev,
  266. sec20chan_freq);
  267. }
  268. void
  269. wlan_lmac_if_sptrl_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
  270. {
  271. struct wlan_lmac_if_sptrl_rx_ops *sptrl_rx_ops = &rx_ops->sptrl_rx_ops;
  272. /* Spectral rx ops */
  273. sptrl_rx_ops->sptrlro_get_pdev_target_handle =
  274. tgt_get_pdev_target_handle;
  275. sptrl_rx_ops->sptrlro_get_psoc_target_handle =
  276. tgt_get_psoc_target_handle;
  277. sptrl_rx_ops->sptrlro_vdev_get_chan_freq = spectral_vdev_get_chan_freq;
  278. sptrl_rx_ops->sptrlro_vdev_get_chan_freq_seg2 =
  279. spectral_vdev_get_chan_freq_seg2;
  280. sptrl_rx_ops->sptrlro_vdev_get_ch_width = spectral_vdev_get_ch_width;
  281. sptrl_rx_ops->sptrlro_vdev_get_sec20chan_freq_mhz =
  282. spectral_vdev_get_sec20chan_freq_mhz;
  283. sptrl_rx_ops->sptrlro_spectral_is_feature_disabled_pdev =
  284. wlan_spectral_is_feature_disabled_pdev;
  285. sptrl_rx_ops->sptrlro_spectral_is_feature_disabled_psoc =
  286. wlan_spectral_is_feature_disabled_psoc;
  287. }
  288. QDF_STATUS
  289. wlan_register_spectral_wmi_ops(struct wlan_objmgr_psoc *psoc,
  290. struct spectral_wmi_ops *wmi_ops)
  291. {
  292. struct spectral_context *sc;
  293. if (!psoc) {
  294. spectral_err("psoc is NULL!");
  295. return QDF_STATUS_E_INVAL;
  296. }
  297. if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
  298. spectral_info("Spectral feature is disabled");
  299. return QDF_STATUS_COMP_DISABLED;
  300. }
  301. sc = spectral_get_spectral_ctx_from_psoc(psoc);
  302. if (!sc) {
  303. spectral_err("spectral context is NULL!");
  304. return QDF_STATUS_E_FAILURE;
  305. }
  306. return sc->sptrlc_register_spectral_wmi_ops(psoc, wmi_ops);
  307. }
  308. qdf_export_symbol(wlan_register_spectral_wmi_ops);
  309. QDF_STATUS
  310. wlan_register_spectral_tgt_ops(struct wlan_objmgr_psoc *psoc,
  311. struct spectral_tgt_ops *tgt_ops)
  312. {
  313. struct spectral_context *sc;
  314. if (!psoc) {
  315. spectral_err("psoc is NULL!");
  316. return QDF_STATUS_E_INVAL;
  317. }
  318. if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
  319. spectral_info("Spectral feature is disabled");
  320. return QDF_STATUS_COMP_DISABLED;
  321. }
  322. sc = spectral_get_spectral_ctx_from_psoc(psoc);
  323. if (!sc) {
  324. spectral_err("spectral context is NULL!");
  325. return QDF_STATUS_E_FAILURE;
  326. }
  327. return sc->sptrlc_register_spectral_tgt_ops(psoc, tgt_ops);
  328. }
  329. qdf_export_symbol(wlan_register_spectral_tgt_ops);
  330. /**
  331. * wlan_spectral_psoc_target_attach() - Spectral psoc target attach
  332. * @psoc: pointer to psoc object
  333. *
  334. * API to initialize Spectral psoc target object
  335. *
  336. * Return: QDF_STATUS_SUCCESS upon successful registration,
  337. * QDF_STATUS_E_FAILURE upon failure
  338. */
  339. static QDF_STATUS
  340. wlan_spectral_psoc_target_attach(struct wlan_objmgr_psoc *psoc)
  341. {
  342. struct spectral_context *sc = NULL;
  343. if (!psoc) {
  344. spectral_err("psoc is null");
  345. return QDF_STATUS_E_FAILURE;
  346. }
  347. sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
  348. WLAN_UMAC_COMP_SPECTRAL);
  349. if (!sc) {
  350. spectral_err("Spectral context is null");
  351. return QDF_STATUS_E_NOMEM;
  352. }
  353. if (sc->sptrlc_psoc_spectral_init) {
  354. void *target_handle;
  355. target_handle = sc->sptrlc_psoc_spectral_init(psoc);
  356. if (!target_handle) {
  357. spectral_err("Spectral psoc lmac object is NULL!");
  358. return QDF_STATUS_E_FAILURE;
  359. }
  360. sc->psoc_target_handle = target_handle;
  361. }
  362. return QDF_STATUS_SUCCESS;
  363. }
  364. /**
  365. * wlan_spectral_psoc_target_detach() - Spectral psoc target detach
  366. * @psoc: pointer to psoc object
  367. *
  368. * API to destroy Spectral psoc target object
  369. *
  370. * Return: QDF_STATUS_SUCCESS upon successful registration,
  371. * QDF_STATUS_E_FAILURE upon failure
  372. */
  373. static QDF_STATUS
  374. wlan_spectral_psoc_target_detach(struct wlan_objmgr_psoc *psoc)
  375. {
  376. struct spectral_context *sc = NULL;
  377. if (!psoc) {
  378. spectral_err("psoc is null");
  379. return QDF_STATUS_E_FAILURE;
  380. }
  381. sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
  382. WLAN_UMAC_COMP_SPECTRAL);
  383. if (!sc) {
  384. spectral_err("Spectral context is null");
  385. return QDF_STATUS_E_INVAL;
  386. }
  387. if (sc->sptrlc_psoc_spectral_deinit)
  388. sc->sptrlc_psoc_spectral_deinit(psoc);
  389. sc->psoc_target_handle = NULL;
  390. return QDF_STATUS_SUCCESS;
  391. }
  392. #ifdef DIRECT_BUF_RX_ENABLE
  393. bool spectral_dbr_event_handler(struct wlan_objmgr_pdev *pdev,
  394. struct direct_buf_rx_data *payload)
  395. {
  396. struct spectral_context *sc;
  397. if (!pdev) {
  398. spectral_err("PDEV is NULL!");
  399. return -EINVAL;
  400. }
  401. sc = spectral_get_spectral_ctx_from_pdev(pdev);
  402. if (!sc) {
  403. spectral_err("spectral context is NULL!");
  404. return -EINVAL;
  405. }
  406. sc->sptrlc_process_spectral_report(pdev, payload);
  407. return true;
  408. }
  409. #endif
  410. QDF_STATUS spectral_pdev_open(struct wlan_objmgr_pdev *pdev)
  411. {
  412. struct wlan_objmgr_psoc *psoc;
  413. QDF_STATUS status;
  414. psoc = wlan_pdev_get_psoc(pdev);
  415. if (wlan_spectral_is_feature_disabled_pdev(pdev)) {
  416. spectral_info("Spectral feature is disabled");
  417. return QDF_STATUS_COMP_DISABLED;
  418. }
  419. if (cfg_get(psoc, CFG_SPECTRAL_POISON_BUFS))
  420. tgt_set_spectral_dma_debug(pdev, SPECTRAL_DMA_BUFFER_DEBUG, 1);
  421. status = spectral_register_dbr(pdev);
  422. return status;
  423. }
  424. QDF_STATUS spectral_register_dbr(struct wlan_objmgr_pdev *pdev)
  425. {
  426. if (wlan_spectral_is_feature_disabled_pdev(pdev)) {
  427. spectral_info("spectral feature is disabled");
  428. return QDF_STATUS_COMP_DISABLED;
  429. }
  430. return tgt_spectral_register_to_dbr(pdev);
  431. }
  432. qdf_export_symbol(spectral_register_dbr);
  433. QDF_STATUS spectral_unregister_dbr(struct wlan_objmgr_pdev *pdev)
  434. {
  435. QDF_STATUS status;
  436. if (wlan_spectral_is_feature_disabled_pdev(pdev)) {
  437. spectral_info("spectral feature is disabled");
  438. return QDF_STATUS_COMP_DISABLED;
  439. }
  440. status = tgt_spectral_unregister_to_dbr(pdev);
  441. return status;
  442. }
  443. qdf_export_symbol(spectral_unregister_dbr);
  444. QDF_STATUS wlan_spectral_psoc_open(struct wlan_objmgr_psoc *psoc)
  445. {
  446. if (!psoc) {
  447. spectral_err("psoc is null");
  448. return QDF_STATUS_E_INVAL;
  449. }
  450. if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
  451. spectral_info("Spectral feature is disabled");
  452. return QDF_STATUS_COMP_DISABLED;
  453. }
  454. return wlan_spectral_psoc_target_attach(psoc);
  455. }
  456. QDF_STATUS wlan_spectral_psoc_close(struct wlan_objmgr_psoc *psoc)
  457. {
  458. if (!psoc) {
  459. spectral_err("psoc is null");
  460. return QDF_STATUS_E_INVAL;
  461. }
  462. if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
  463. spectral_info("Spectral feature is disabled");
  464. return QDF_STATUS_COMP_DISABLED;
  465. }
  466. return wlan_spectral_psoc_target_detach(psoc);
  467. }
  468. QDF_STATUS wlan_spectral_psoc_enable(struct wlan_objmgr_psoc *psoc)
  469. {
  470. if (!psoc) {
  471. spectral_err("psoc is null");
  472. return QDF_STATUS_E_INVAL;
  473. }
  474. if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
  475. spectral_info("Spectral feature is disabled");
  476. return QDF_STATUS_COMP_DISABLED;
  477. }
  478. return tgt_spectral_register_events(psoc);
  479. }
  480. QDF_STATUS wlan_spectral_psoc_disable(struct wlan_objmgr_psoc *psoc)
  481. {
  482. if (!psoc) {
  483. spectral_err("psoc is null");
  484. return QDF_STATUS_E_INVAL;
  485. }
  486. if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
  487. spectral_info("Spectral feature is disabled");
  488. return QDF_STATUS_COMP_DISABLED;
  489. }
  490. return tgt_spectral_unregister_events(psoc);
  491. }
  492. struct wlan_lmac_if_sptrl_tx_ops *
  493. wlan_spectral_pdev_get_lmac_if_txops(struct wlan_objmgr_pdev *pdev)
  494. {
  495. struct wlan_objmgr_psoc *psoc;
  496. struct wlan_lmac_if_tx_ops *tx_ops;
  497. if (!pdev) {
  498. spectral_err("pdev is NULL!");
  499. return NULL;
  500. }
  501. psoc = wlan_pdev_get_psoc(pdev);
  502. if (!psoc) {
  503. spectral_err("psoc is NULL!");
  504. return NULL;
  505. }
  506. tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
  507. if (!tx_ops) {
  508. spectral_err("tx_ops is NULL");
  509. return NULL;
  510. }
  511. return &tx_ops->sptrl_tx_ops;
  512. }