wlan_ocb_ucfg_api.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. /*
  2. * Copyright (c) 2018 The Linux Foundation. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for
  5. * any purpose with or without fee is hereby granted, provided that the
  6. * above copyright notice and this permission notice appear in all
  7. * copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  10. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  11. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  12. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  13. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  14. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  15. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  16. * PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. /**
  19. * DOC: This file contains ocb north bound interface definitions
  20. */
  21. #include <scheduler_api.h>
  22. #include <wlan_defs.h>
  23. #include <wlan_reg_services_api.h>
  24. #include <wlan_objmgr_psoc_obj.h>
  25. #include <wlan_objmgr_global_obj.h>
  26. #include <wlan_ocb_public_structs.h>
  27. #include <wlan_ocb_ucfg_api.h>
  28. #include <wlan_ocb_tgt_api.h>
  29. #include <wlan_lmac_if_def.h>
  30. #include "wlan_ocb_main.h"
  31. /**
  32. * wlan_ocb_get_tx_ops() - get target interface tx operations
  33. * @pdev: pdev handle
  34. *
  35. * Return: fp to target interface operations
  36. */
  37. static struct wlan_ocb_tx_ops *
  38. wlan_ocb_get_tx_ops(struct wlan_objmgr_pdev *pdev)
  39. {
  40. struct ocb_pdev_obj *ocb_obj;
  41. ocb_obj = wlan_get_pdev_ocb_obj(pdev);
  42. if (!ocb_obj) {
  43. ocb_err("failed to get OCB pdev object");
  44. return NULL;
  45. }
  46. return &ocb_obj->ocb_txops;
  47. }
  48. QDF_STATUS ucfg_ocb_init(void)
  49. {
  50. QDF_STATUS status;
  51. ocb_notice("ocb module dispatcher init");
  52. status = wlan_objmgr_register_pdev_create_handler(WLAN_UMAC_COMP_OCB,
  53. ocb_pdev_obj_create_notification, NULL);
  54. if (QDF_IS_STATUS_ERROR(status)) {
  55. ocb_err("Failed to register pdev create handler for ocb");
  56. return status;
  57. }
  58. status = wlan_objmgr_register_pdev_destroy_handler(WLAN_UMAC_COMP_OCB,
  59. ocb_pdev_obj_destroy_notification, NULL);
  60. if (QDF_IS_STATUS_ERROR(status)) {
  61. ocb_err("Failed to register pdev destroy handler for ocb");
  62. goto fail_delete_pdev;
  63. }
  64. return status;
  65. fail_delete_pdev:
  66. wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_OCB,
  67. ocb_pdev_obj_create_notification, NULL);
  68. return status;
  69. }
  70. QDF_STATUS ucfg_ocb_deinit(void)
  71. {
  72. QDF_STATUS status;
  73. ocb_notice("ocb module dispatcher deinit");
  74. status = wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_OCB,
  75. ocb_pdev_obj_destroy_notification, NULL);
  76. if (QDF_IS_STATUS_ERROR(status))
  77. ocb_err("Failed to unregister pdev destroy handler");
  78. status = wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_OCB,
  79. ocb_pdev_obj_create_notification, NULL);
  80. if (QDF_IS_STATUS_ERROR(status))
  81. ocb_err("Failed to unregister pdev create handler");
  82. return status;
  83. }
  84. QDF_STATUS ocb_psoc_enable(struct wlan_objmgr_psoc *psoc)
  85. {
  86. struct wlan_objmgr_pdev *pdev;
  87. pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
  88. WLAN_OCB_NB_ID);
  89. if (!pdev) {
  90. ocb_err("Failed to get pdev handle");
  91. return QDF_STATUS_E_FAILURE;
  92. }
  93. tgt_ocb_register_ev_handler(pdev);
  94. wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_NB_ID);
  95. return QDF_STATUS_SUCCESS;
  96. }
  97. QDF_STATUS ocb_psoc_disable(struct wlan_objmgr_psoc *psoc)
  98. {
  99. struct wlan_objmgr_pdev *pdev;
  100. pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
  101. WLAN_OCB_NB_ID);
  102. if (!pdev) {
  103. ocb_err("Failed to get pdev handle");
  104. return QDF_STATUS_E_FAILURE;
  105. }
  106. tgt_ocb_unregister_ev_handler(pdev);
  107. wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_NB_ID);
  108. return QDF_STATUS_SUCCESS;
  109. }
  110. QDF_STATUS ucfg_ocb_set_txrx_handle(struct wlan_objmgr_psoc *psoc,
  111. void *txrx_handle)
  112. {
  113. struct wlan_objmgr_pdev *pdev;
  114. struct ocb_pdev_obj *ocb_obj;
  115. pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
  116. WLAN_OCB_NB_ID);
  117. if (!pdev) {
  118. ocb_err("Failed to get pdev handle");
  119. return QDF_STATUS_E_FAILURE;
  120. }
  121. ocb_obj = wlan_get_pdev_ocb_obj(pdev);
  122. wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_NB_ID);
  123. if (!ocb_obj) {
  124. ocb_err("OCB object is NULL");
  125. return QDF_STATUS_E_FAILURE;
  126. }
  127. ocb_obj->dp_pdev = txrx_handle;
  128. return QDF_STATUS_SUCCESS;
  129. }
  130. QDF_STATUS ucfg_ocb_update_dp_handle(struct wlan_objmgr_psoc *psoc,
  131. void *dp_soc)
  132. {
  133. struct wlan_objmgr_pdev *pdev;
  134. struct ocb_pdev_obj *ocb_obj;
  135. pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
  136. WLAN_OCB_NB_ID);
  137. if (!pdev) {
  138. ocb_err("Failed to get pdev handle");
  139. return QDF_STATUS_E_FAILURE;
  140. }
  141. ocb_obj = wlan_get_pdev_ocb_obj(pdev);
  142. wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_NB_ID);
  143. if (!ocb_obj) {
  144. ocb_err("OCB object is NULL");
  145. return QDF_STATUS_E_FAILURE;
  146. }
  147. ocb_obj->dp_soc = dp_soc;
  148. return QDF_STATUS_SUCCESS;
  149. }
  150. QDF_STATUS ucfg_ocb_config_channel(struct wlan_objmgr_pdev *pdev)
  151. {
  152. QDF_STATUS status;
  153. struct ocb_config *config;
  154. struct ocb_pdev_obj *ocb_obj;
  155. struct wlan_objmgr_psoc *psoc;
  156. struct wlan_ocb_tx_ops *tx_ops;
  157. ocb_obj = wlan_get_pdev_ocb_obj(pdev);
  158. if (!ocb_obj || !ocb_obj->channel_config) {
  159. ocb_alert("The request could not be found");
  160. return QDF_STATUS_E_FAILURE;
  161. }
  162. config = ocb_obj->channel_config;
  163. ocb_debug("Set config to vdev%d", config->vdev_id);
  164. psoc = wlan_pdev_get_psoc(pdev);
  165. if (!psoc) {
  166. ocb_err("Null pointer for psoc");
  167. return QDF_STATUS_E_INVAL;
  168. }
  169. tx_ops = wlan_ocb_get_tx_ops(pdev);
  170. if (tx_ops && tx_ops->ocb_set_config)
  171. status = tx_ops->ocb_set_config(psoc, ocb_obj->channel_config);
  172. else
  173. status = QDF_STATUS_E_IO;
  174. if (QDF_IS_STATUS_SUCCESS(status)) {
  175. ocb_debug("Set channel cmd is sent to southbound");
  176. } else {
  177. ocb_err("Failed to set channel config to southbound");
  178. if (ocb_obj->channel_config) {
  179. /*
  180. * On success case, backup parameters will be released
  181. * after channel info is synced to DP
  182. */
  183. ocb_info("release the backed config parameters");
  184. qdf_mem_free(ocb_obj->channel_config);
  185. ocb_obj->channel_config = NULL;
  186. }
  187. }
  188. return status;
  189. }
  190. QDF_STATUS ucfg_ocb_set_channel_config(struct wlan_objmgr_vdev *vdev,
  191. struct ocb_config *config,
  192. ocb_sync_callback set_config_cb,
  193. void *arg)
  194. {
  195. QDF_STATUS status;
  196. enum wlan_vdev_state state;
  197. uint32_t i;
  198. struct wlan_objmgr_pdev *pdev;
  199. struct wlan_objmgr_psoc *psoc;
  200. struct wlan_ocb_tx_ops *tx_ops;
  201. struct ocb_pdev_obj *ocb_obj;
  202. struct ocb_callbacks *ocb_cbs;
  203. pdev = wlan_vdev_get_pdev(vdev);
  204. if (!pdev) {
  205. ocb_err("Null pointer for pdev");
  206. return QDF_STATUS_E_INVAL;
  207. }
  208. ocb_obj = wlan_get_pdev_ocb_obj(pdev);
  209. if (!ocb_obj) {
  210. ocb_alert("Failed to get OCB vdev object");
  211. return QDF_STATUS_E_IO;
  212. }
  213. if (!config) {
  214. ocb_err("Invalid config input");
  215. return QDF_STATUS_E_FAILURE;
  216. }
  217. for (i = 0; i < config->channel_count; i++) {
  218. if (WLAN_REG_CHAN_TO_BAND(wlan_reg_freq_to_chan(pdev,
  219. config->channels[i].chan_freq))
  220. == BAND_2G)
  221. config->channels[i].ch_mode = MODE_11G;
  222. else
  223. config->channels[i].ch_mode = MODE_11A;
  224. }
  225. /*
  226. * backup the new configuration,
  227. * it will be released after target's response
  228. */
  229. ocb_obj->channel_config = ocb_copy_config(config);
  230. if (!ocb_obj->channel_config) {
  231. ocb_err("Failed to backup config");
  232. return QDF_STATUS_E_NOMEM;
  233. }
  234. ocb_cbs = &ocb_obj->ocb_cbs;
  235. ocb_cbs->ocb_set_config_callback = set_config_cb;
  236. ocb_cbs->ocb_set_config_context = arg;
  237. state = wlan_vdev_mlme_get_state(vdev);
  238. if (state != WLAN_VDEV_S_RUN) {
  239. /* Vdev is not started, start it */
  240. ocb_debug("OCB vdev%d is not up", config->vdev_id);
  241. status = ocb_vdev_start(ocb_obj);
  242. } else {
  243. psoc = wlan_vdev_get_psoc(vdev);
  244. tx_ops = wlan_ocb_get_tx_ops(pdev);
  245. if (tx_ops && tx_ops->ocb_set_config)
  246. status = tx_ops->ocb_set_config(psoc, config);
  247. else
  248. status = QDF_STATUS_E_IO;
  249. ocb_debug("Set config to vdev%d", config->vdev_id);
  250. if (QDF_IS_STATUS_SUCCESS(status))
  251. ocb_debug("Set channel cmd is sent to southbound");
  252. else
  253. ocb_err("Failed to set channel config to southbound");
  254. }
  255. if (QDF_IS_STATUS_ERROR(status) && ocb_obj->channel_config) {
  256. /*
  257. * On success case, backup parameters will be released
  258. * after channel info is synced to DP
  259. */
  260. ocb_info("release the backed config parameters");
  261. qdf_mem_free(ocb_obj->channel_config);
  262. ocb_obj->channel_config = NULL;
  263. }
  264. return status;
  265. }
  266. QDF_STATUS ucfg_ocb_set_utc_time(struct wlan_objmgr_vdev *vdev,
  267. struct ocb_utc_param *utc)
  268. {
  269. QDF_STATUS status;
  270. struct wlan_objmgr_psoc *psoc;
  271. struct wlan_objmgr_pdev *pdev;
  272. struct wlan_ocb_tx_ops *tx_ops;
  273. psoc = wlan_vdev_get_psoc(vdev);
  274. pdev = wlan_vdev_get_pdev(vdev);
  275. if (!psoc || !pdev) {
  276. ocb_err("Null pointer for psoc/pdev");
  277. return QDF_STATUS_E_INVAL;
  278. }
  279. tx_ops = wlan_ocb_get_tx_ops(pdev);
  280. if (!tx_ops) {
  281. ocb_alert("tx_ops is null");
  282. return QDF_STATUS_E_IO;
  283. }
  284. if (!tx_ops->ocb_set_utc_time) {
  285. ocb_alert("ocb_set_utc_time is null");
  286. return QDF_STATUS_E_IO;
  287. }
  288. status = tx_ops->ocb_set_utc_time(psoc, utc);
  289. if (QDF_IS_STATUS_ERROR(status))
  290. ocb_err("Failed to set UTC time to southbound");
  291. else
  292. ocb_debug("UTC time is sent to southbound");
  293. return status;
  294. }
  295. QDF_STATUS ucfg_ocb_start_timing_advert(struct wlan_objmgr_vdev *vdev,
  296. struct ocb_timing_advert_param *ta)
  297. {
  298. QDF_STATUS status;
  299. struct wlan_objmgr_psoc *psoc;
  300. struct wlan_objmgr_pdev *pdev;
  301. struct wlan_ocb_tx_ops *tx_ops;
  302. psoc = wlan_vdev_get_psoc(vdev);
  303. pdev = wlan_vdev_get_pdev(vdev);
  304. if (!psoc || !pdev) {
  305. ocb_err("Null pointer for psoc/pdev");
  306. return QDF_STATUS_E_INVAL;
  307. }
  308. tx_ops = wlan_ocb_get_tx_ops(pdev);
  309. if (!tx_ops) {
  310. ocb_alert("tx_ops is null");
  311. return QDF_STATUS_E_IO;
  312. }
  313. if (!tx_ops->ocb_start_timing_advert) {
  314. ocb_alert("ocb_start_timing_advert is null");
  315. return QDF_STATUS_E_IO;
  316. }
  317. status = tx_ops->ocb_start_timing_advert(psoc, ta);
  318. if (QDF_IS_STATUS_ERROR(status))
  319. ocb_err("Failed to sent start timing advert to southbound");
  320. else
  321. ocb_debug("Start timing advert is sent to southbound");
  322. return status;
  323. }
  324. QDF_STATUS ucfg_ocb_stop_timing_advert(struct wlan_objmgr_vdev *vdev,
  325. struct ocb_timing_advert_param *ta)
  326. {
  327. QDF_STATUS status;
  328. struct wlan_objmgr_psoc *psoc;
  329. struct wlan_objmgr_pdev *pdev;
  330. struct wlan_ocb_tx_ops *tx_ops;
  331. psoc = wlan_vdev_get_psoc(vdev);
  332. pdev = wlan_vdev_get_pdev(vdev);
  333. if (!psoc || !pdev) {
  334. ocb_err("Null pointer for psoc/pdev");
  335. return QDF_STATUS_E_INVAL;
  336. }
  337. tx_ops = wlan_ocb_get_tx_ops(pdev);
  338. if (!tx_ops) {
  339. ocb_alert("tx_ops is null");
  340. return QDF_STATUS_E_IO;
  341. }
  342. if (!tx_ops->ocb_stop_timing_advert) {
  343. ocb_alert("ocb_stop_timing_advert is null");
  344. return QDF_STATUS_E_IO;
  345. }
  346. status = tx_ops->ocb_stop_timing_advert(psoc, ta);
  347. if (QDF_IS_STATUS_ERROR(status))
  348. ocb_err("Failed to sent start timing advert to southbound");
  349. else
  350. ocb_debug("Start timing advert is sent to southbound");
  351. return status;
  352. }
  353. QDF_STATUS ucfg_ocb_get_tsf_timer(struct wlan_objmgr_vdev *vdev,
  354. struct ocb_get_tsf_timer_param *req,
  355. ocb_sync_callback get_tsf_cb,
  356. void *arg)
  357. {
  358. QDF_STATUS status;
  359. struct wlan_objmgr_psoc *psoc;
  360. struct ocb_get_tsf_timer_param request;
  361. struct wlan_ocb_tx_ops *tx_ops;
  362. struct ocb_callbacks *ocb_cbs;
  363. struct wlan_objmgr_pdev *pdev;
  364. pdev = wlan_vdev_get_pdev(vdev);
  365. if (!pdev) {
  366. ocb_err("Null pointer for pdev");
  367. return QDF_STATUS_E_INVAL;
  368. }
  369. tx_ops = wlan_ocb_get_tx_ops(pdev);
  370. if (!tx_ops) {
  371. ocb_alert("tx_ops is null");
  372. return QDF_STATUS_E_IO;
  373. }
  374. if (!tx_ops->ocb_get_tsf_timer) {
  375. ocb_alert("ocb_get_tsf_timer is null");
  376. return QDF_STATUS_E_IO;
  377. }
  378. ocb_cbs = wlan_ocb_get_callbacks(pdev);
  379. ocb_cbs->ocb_get_tsf_timer_context = arg;
  380. ocb_cbs->ocb_get_tsf_timer_callback = get_tsf_cb;
  381. request.vdev_id = req->vdev_id;
  382. psoc = wlan_vdev_get_psoc(vdev);
  383. if (!psoc) {
  384. ocb_err("Null pointer for psoc");
  385. return QDF_STATUS_E_INVAL;
  386. }
  387. status = tx_ops->ocb_get_tsf_timer(psoc, &request);
  388. if (QDF_IS_STATUS_ERROR(status))
  389. ocb_err("Failed to sent get tsf timer to southbound");
  390. else
  391. ocb_debug("Get tsf timer is sent to southbound");
  392. return status;
  393. }
  394. QDF_STATUS ucfg_ocb_dcc_get_stats(struct wlan_objmgr_vdev *vdev,
  395. struct ocb_dcc_get_stats_param *request,
  396. ocb_sync_callback dcc_get_stats_cb,
  397. void *arg)
  398. {
  399. QDF_STATUS status;
  400. struct wlan_objmgr_psoc *psoc;
  401. struct wlan_objmgr_pdev *pdev;
  402. struct ocb_callbacks *ocb_cbs;
  403. struct wlan_ocb_tx_ops *tx_ops;
  404. pdev = wlan_vdev_get_pdev(vdev);
  405. if (!pdev) {
  406. ocb_err("Null pointer for pdev");
  407. return QDF_STATUS_E_INVAL;
  408. }
  409. ocb_cbs = wlan_ocb_get_callbacks(pdev);
  410. ocb_cbs->ocb_dcc_get_stats_context = arg;
  411. ocb_cbs->ocb_dcc_get_stats_callback = dcc_get_stats_cb;
  412. tx_ops = wlan_ocb_get_tx_ops(pdev);
  413. if (!tx_ops) {
  414. ocb_alert("tx_ops is null");
  415. return QDF_STATUS_E_IO;
  416. }
  417. if (!tx_ops->ocb_dcc_get_stats) {
  418. ocb_alert("ocb_dcc_get_stats is null");
  419. return QDF_STATUS_E_IO;
  420. }
  421. psoc = wlan_vdev_get_psoc(vdev);
  422. if (!psoc) {
  423. ocb_err("Null pointer for psoc");
  424. return QDF_STATUS_E_INVAL;
  425. }
  426. status = tx_ops->ocb_dcc_get_stats(psoc, request);
  427. if (QDF_IS_STATUS_ERROR(status))
  428. ocb_err("Failed to sent get dcc stats to southbound");
  429. else
  430. ocb_debug("Get dcc stats is sent to southbound");
  431. return status;
  432. }
  433. QDF_STATUS ucfg_ocb_dcc_clear_stats(struct wlan_objmgr_vdev *vdev,
  434. uint16_t vdev_id,
  435. uint32_t bitmap)
  436. {
  437. QDF_STATUS status;
  438. struct wlan_objmgr_psoc *psoc;
  439. struct wlan_objmgr_pdev *pdev;
  440. struct wlan_ocb_tx_ops *tx_ops;
  441. struct ocb_dcc_clear_stats_param clear_stats_param;
  442. pdev = wlan_vdev_get_pdev(vdev);
  443. if (!pdev) {
  444. ocb_err("Null pointer for pdev");
  445. return QDF_STATUS_E_INVAL;
  446. }
  447. tx_ops = wlan_ocb_get_tx_ops(pdev);
  448. if (!tx_ops) {
  449. ocb_alert("tx_ops is null");
  450. return QDF_STATUS_E_IO;
  451. }
  452. if (!tx_ops->ocb_dcc_clear_stats) {
  453. ocb_alert("ocb_dcc_clear_stats is null");
  454. return QDF_STATUS_E_IO;
  455. }
  456. clear_stats_param.vdev_id = vdev_id;
  457. clear_stats_param.dcc_stats_bitmap = bitmap;
  458. psoc = wlan_vdev_get_psoc(vdev);
  459. if (!psoc) {
  460. ocb_err("Null pointer for psoc");
  461. return QDF_STATUS_E_INVAL;
  462. }
  463. status = tx_ops->ocb_dcc_clear_stats(psoc, &clear_stats_param);
  464. if (QDF_IS_STATUS_ERROR(status))
  465. ocb_err("Failed to sent clear dcc stats to southbound");
  466. else
  467. ocb_debug("clear dcc stats is sent to southbound");
  468. return status;
  469. }
  470. QDF_STATUS ucfg_ocb_dcc_update_ndl(struct wlan_objmgr_vdev *vdev,
  471. struct ocb_dcc_update_ndl_param *request,
  472. ocb_sync_callback dcc_update_ndl_cb,
  473. void *arg)
  474. {
  475. QDF_STATUS status;
  476. struct wlan_objmgr_psoc *psoc;
  477. struct ocb_callbacks *ocb_cbs;
  478. struct wlan_objmgr_pdev *pdev;
  479. struct wlan_ocb_tx_ops *tx_ops;
  480. pdev = wlan_vdev_get_pdev(vdev);
  481. if (!pdev) {
  482. ocb_err("Null pointer for pdev");
  483. return QDF_STATUS_E_INVAL;
  484. }
  485. ocb_cbs = wlan_ocb_get_callbacks(pdev);
  486. ocb_cbs->ocb_dcc_update_ndl_context = arg;
  487. ocb_cbs->ocb_dcc_update_ndl_callback = dcc_update_ndl_cb;
  488. tx_ops = wlan_ocb_get_tx_ops(pdev);
  489. if (!tx_ops) {
  490. ocb_alert("tx_ops is null");
  491. return QDF_STATUS_E_IO;
  492. }
  493. if (!tx_ops->ocb_dcc_update_ndl) {
  494. ocb_alert("dcc_update_ndl is null");
  495. return QDF_STATUS_E_IO;
  496. }
  497. psoc = wlan_vdev_get_psoc(vdev);
  498. if (!psoc) {
  499. ocb_err("Null pointer for psoc");
  500. return QDF_STATUS_E_INVAL;
  501. }
  502. status = tx_ops->ocb_dcc_update_ndl(psoc, request);
  503. if (QDF_IS_STATUS_ERROR(status))
  504. ocb_err("Failed to sent update ndl to southbound");
  505. else
  506. ocb_debug("Update ndl is sent to southbound");
  507. return status;
  508. }
  509. QDF_STATUS ucfg_ocb_register_for_dcc_stats_event(struct wlan_objmgr_pdev *pdev,
  510. void *ctx, ocb_sync_callback dcc_stats_cb)
  511. {
  512. struct ocb_callbacks *ocb_cbs;
  513. if (!pdev) {
  514. ocb_err("Null pointer for pdev");
  515. return QDF_STATUS_E_INVAL;
  516. }
  517. ocb_cbs = wlan_ocb_get_callbacks(pdev);
  518. if (!ocb_cbs) {
  519. ocb_err("Failed to register dcc stats callback");
  520. return QDF_STATUS_E_FAILURE;
  521. }
  522. ocb_cbs->ocb_dcc_stats_event_context = ctx;
  523. ocb_cbs->ocb_dcc_stats_event_callback = dcc_stats_cb;
  524. return QDF_STATUS_SUCCESS;
  525. }
  526. QDF_STATUS ucfg_ocb_register_vdev_start(struct wlan_objmgr_pdev *pdev,
  527. QDF_STATUS (*ocb_start)(struct ocb_config *))
  528. {
  529. struct ocb_callbacks *ocb_cbs;
  530. if (!pdev) {
  531. ocb_err("Null pointer for pdev");
  532. return QDF_STATUS_E_INVAL;
  533. }
  534. ocb_cbs = wlan_ocb_get_callbacks(pdev);
  535. if (!ocb_cbs) {
  536. ocb_err("Failed to register dcc stats callback");
  537. return QDF_STATUS_E_FAILURE;
  538. }
  539. ocb_cbs->start_ocb_vdev = ocb_start;
  540. return QDF_STATUS_SUCCESS;
  541. }