dp_mlo.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. /*
  2. * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include <wlan_utility.h>
  17. #include <dp_internal.h>
  18. #include <dp_htt.h>
  19. #include <hal_be_api.h>
  20. #include "dp_mlo.h"
  21. #include <dp_be.h>
  22. #include <dp_be_rx.h>
  23. #include <dp_htt.h>
  24. #include <dp_internal.h>
  25. #include <wlan_cfg.h>
  26. #include <wlan_mlo_mgr_cmn.h>
  27. /**
  28. * dp_mlo_ctxt_attach_wifi3() - Attach DP MLO context
  29. * @ctrl_ctxt: CDP control context
  30. *
  31. * Return: DP MLO context handle on success, NULL on failure
  32. */
  33. static struct cdp_mlo_ctxt *
  34. dp_mlo_ctxt_attach_wifi3(struct cdp_ctrl_mlo_mgr *ctrl_ctxt)
  35. {
  36. struct dp_mlo_ctxt *mlo_ctxt =
  37. qdf_mem_malloc(sizeof(struct dp_mlo_ctxt));
  38. if (!mlo_ctxt) {
  39. dp_err("Failed to allocate DP MLO Context");
  40. return NULL;
  41. }
  42. mlo_ctxt->ctrl_ctxt = ctrl_ctxt;
  43. if (dp_mlo_peer_find_hash_attach_be
  44. (mlo_ctxt, DP_MAX_MLO_PEER) != QDF_STATUS_SUCCESS) {
  45. dp_err("Failed to allocate peer hash");
  46. qdf_mem_free(mlo_ctxt);
  47. return NULL;
  48. }
  49. qdf_get_random_bytes(mlo_ctxt->toeplitz_hash_ipv4,
  50. (sizeof(mlo_ctxt->toeplitz_hash_ipv4[0]) *
  51. LRO_IPV4_SEED_ARR_SZ));
  52. qdf_get_random_bytes(mlo_ctxt->toeplitz_hash_ipv6,
  53. (sizeof(mlo_ctxt->toeplitz_hash_ipv6[0]) *
  54. LRO_IPV6_SEED_ARR_SZ));
  55. qdf_spinlock_create(&mlo_ctxt->ml_soc_list_lock);
  56. return dp_mlo_ctx_to_cdp(mlo_ctxt);
  57. }
  58. /**
  59. * dp_mlo_ctxt_detach_wifi3() - Detach DP MLO context
  60. * @cdp_ml_ctxt: pointer to CDP DP MLO context
  61. *
  62. * Return: void
  63. */
  64. static void dp_mlo_ctxt_detach_wifi3(struct cdp_mlo_ctxt *cdp_ml_ctxt)
  65. {
  66. struct dp_mlo_ctxt *mlo_ctxt = cdp_mlo_ctx_to_dp(cdp_ml_ctxt);
  67. if (!cdp_ml_ctxt)
  68. return;
  69. qdf_spinlock_destroy(&mlo_ctxt->ml_soc_list_lock);
  70. dp_mlo_peer_find_hash_detach_be(mlo_ctxt);
  71. qdf_mem_free(mlo_ctxt);
  72. }
  73. /**
  74. * dp_mlo_set_soc_by_chip_id() - Add DP soc to ML context soc list
  75. * @ml_ctxt: DP ML context handle
  76. * @soc: DP soc handle
  77. * @chip_id: MLO chip id
  78. *
  79. * Return: void
  80. */
  81. static void dp_mlo_set_soc_by_chip_id(struct dp_mlo_ctxt *ml_ctxt,
  82. struct dp_soc *soc,
  83. uint8_t chip_id)
  84. {
  85. qdf_spin_lock_bh(&ml_ctxt->ml_soc_list_lock);
  86. ml_ctxt->ml_soc_list[chip_id] = soc;
  87. /* The same API is called during soc_attach and soc_detach
  88. * soc parameter is non-null or null accordingly.
  89. */
  90. if (soc)
  91. ml_ctxt->ml_soc_cnt++;
  92. else
  93. ml_ctxt->ml_soc_cnt--;
  94. qdf_spin_unlock_bh(&ml_ctxt->ml_soc_list_lock);
  95. }
  96. struct dp_soc*
  97. dp_mlo_get_soc_ref_by_chip_id(struct dp_mlo_ctxt *ml_ctxt,
  98. uint8_t chip_id)
  99. {
  100. struct dp_soc *soc = NULL;
  101. if (!ml_ctxt) {
  102. dp_warn("MLO context not created, MLO not enabled");
  103. return NULL;
  104. }
  105. qdf_spin_lock_bh(&ml_ctxt->ml_soc_list_lock);
  106. soc = ml_ctxt->ml_soc_list[chip_id];
  107. if (!soc) {
  108. qdf_spin_unlock_bh(&ml_ctxt->ml_soc_list_lock);
  109. return NULL;
  110. }
  111. qdf_atomic_inc(&soc->ref_count);
  112. qdf_spin_unlock_bh(&ml_ctxt->ml_soc_list_lock);
  113. return soc;
  114. }
  115. static QDF_STATUS dp_partner_soc_rx_hw_cc_init(struct dp_mlo_ctxt *mlo_ctxt,
  116. struct dp_soc_be *be_soc)
  117. {
  118. uint8_t i;
  119. struct dp_soc *partner_soc;
  120. struct dp_soc_be *be_partner_soc;
  121. uint8_t pool_id;
  122. QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
  123. for (i = 0; i < WLAN_MAX_MLO_CHIPS; i++) {
  124. partner_soc = dp_mlo_get_soc_ref_by_chip_id(mlo_ctxt, i);
  125. if (!partner_soc) {
  126. dp_err("partner_soc is NULL");
  127. continue;
  128. }
  129. be_partner_soc = dp_get_be_soc_from_dp_soc(partner_soc);
  130. for (pool_id = 0; pool_id < MAX_RXDESC_POOLS; pool_id++) {
  131. qdf_status =
  132. dp_hw_cookie_conversion_init
  133. (be_soc,
  134. &be_partner_soc->rx_cc_ctx[pool_id]);
  135. if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
  136. dp_alert("MLO partner soc RX CC init failed");
  137. return qdf_status;
  138. }
  139. }
  140. }
  141. return qdf_status;
  142. }
  143. static void dp_mlo_soc_drain_rx_buf(struct dp_soc *soc, void *arg)
  144. {
  145. uint8_t i = 0;
  146. uint8_t cpu = 0;
  147. uint8_t rx_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = {0};
  148. uint8_t rx_err_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = {0};
  149. uint8_t rx_wbm_rel_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = {0};
  150. uint8_t reo_status_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = {0};
  151. /* Save the current interrupt mask and disable the interrupts */
  152. for (i = 0; i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++) {
  153. rx_ring_mask[i] = soc->intr_ctx[i].rx_ring_mask;
  154. rx_err_ring_mask[i] = soc->intr_ctx[i].rx_err_ring_mask;
  155. rx_wbm_rel_ring_mask[i] = soc->intr_ctx[i].rx_wbm_rel_ring_mask;
  156. reo_status_ring_mask[i] = soc->intr_ctx[i].reo_status_ring_mask;
  157. soc->intr_ctx[i].rx_ring_mask = 0;
  158. soc->intr_ctx[i].rx_err_ring_mask = 0;
  159. soc->intr_ctx[i].rx_wbm_rel_ring_mask = 0;
  160. soc->intr_ctx[i].reo_status_ring_mask = 0;
  161. }
  162. /* make sure dp_service_srngs not running on any of the CPU */
  163. for (cpu = 0; cpu < NR_CPUS; cpu++) {
  164. while (qdf_atomic_test_bit(cpu,
  165. &soc->service_rings_running))
  166. ;
  167. }
  168. for (i = 0; i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++) {
  169. uint8_t ring = 0;
  170. uint32_t num_entries = 0;
  171. hal_ring_handle_t hal_ring_hdl = NULL;
  172. uint8_t rx_mask = wlan_cfg_get_rx_ring_mask(
  173. soc->wlan_cfg_ctx, i);
  174. uint8_t rx_err_mask = wlan_cfg_get_rx_err_ring_mask(
  175. soc->wlan_cfg_ctx, i);
  176. uint8_t rx_wbm_rel_mask = wlan_cfg_get_rx_wbm_rel_ring_mask(
  177. soc->wlan_cfg_ctx, i);
  178. if (rx_mask) {
  179. /* iterate through each reo ring and process the buf */
  180. for (ring = 0; ring < soc->num_reo_dest_rings; ring++) {
  181. if (!(rx_mask & (1 << ring)))
  182. continue;
  183. hal_ring_hdl =
  184. soc->reo_dest_ring[ring].hal_srng;
  185. num_entries = hal_srng_get_num_entries(
  186. soc->hal_soc,
  187. hal_ring_hdl);
  188. dp_rx_process_be(&soc->intr_ctx[i],
  189. hal_ring_hdl,
  190. ring,
  191. num_entries);
  192. }
  193. }
  194. /* Process REO Exception ring */
  195. if (rx_err_mask) {
  196. hal_ring_hdl = soc->reo_exception_ring.hal_srng;
  197. num_entries = hal_srng_get_num_entries(
  198. soc->hal_soc,
  199. hal_ring_hdl);
  200. dp_rx_err_process(&soc->intr_ctx[i], soc,
  201. hal_ring_hdl, num_entries);
  202. }
  203. /* Process Rx WBM release ring */
  204. if (rx_wbm_rel_mask) {
  205. hal_ring_hdl = soc->rx_rel_ring.hal_srng;
  206. num_entries = hal_srng_get_num_entries(
  207. soc->hal_soc,
  208. hal_ring_hdl);
  209. dp_rx_wbm_err_process(&soc->intr_ctx[i], soc,
  210. hal_ring_hdl, num_entries);
  211. }
  212. }
  213. /* restore the interrupt mask */
  214. for (i = 0; i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++) {
  215. soc->intr_ctx[i].rx_ring_mask = rx_ring_mask[i];
  216. soc->intr_ctx[i].rx_err_ring_mask = rx_err_ring_mask[i];
  217. soc->intr_ctx[i].rx_wbm_rel_ring_mask = rx_wbm_rel_ring_mask[i];
  218. soc->intr_ctx[i].reo_status_ring_mask = reo_status_ring_mask[i];
  219. }
  220. }
  221. static void dp_mlo_soc_setup(struct cdp_soc_t *soc_hdl,
  222. struct cdp_mlo_ctxt *cdp_ml_ctxt)
  223. {
  224. struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
  225. struct dp_mlo_ctxt *mlo_ctxt = cdp_mlo_ctx_to_dp(cdp_ml_ctxt);
  226. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  227. uint8_t pdev_id;
  228. if (!cdp_ml_ctxt)
  229. return;
  230. be_soc->ml_ctxt = mlo_ctxt;
  231. for (pdev_id = 0; pdev_id < MAX_PDEV_CNT; pdev_id++) {
  232. if (soc->pdev_list[pdev_id])
  233. dp_mlo_update_link_to_pdev_map(soc,
  234. soc->pdev_list[pdev_id]);
  235. }
  236. dp_mlo_set_soc_by_chip_id(mlo_ctxt, soc, be_soc->mlo_chip_id);
  237. }
  238. static void dp_mlo_soc_teardown(struct cdp_soc_t *soc_hdl,
  239. struct cdp_mlo_ctxt *cdp_ml_ctxt,
  240. bool is_force_down)
  241. {
  242. struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
  243. struct dp_mlo_ctxt *mlo_ctxt = cdp_mlo_ctx_to_dp(cdp_ml_ctxt);
  244. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  245. if (!cdp_ml_ctxt)
  246. return;
  247. /* During the teardown drain the Rx buffers if any exist in the ring */
  248. dp_mlo_iter_ptnr_soc(be_soc,
  249. dp_mlo_soc_drain_rx_buf,
  250. NULL);
  251. dp_mlo_set_soc_by_chip_id(mlo_ctxt, NULL, be_soc->mlo_chip_id);
  252. be_soc->ml_ctxt = NULL;
  253. }
  254. static QDF_STATUS dp_mlo_add_ptnr_vdev(struct dp_vdev *vdev1,
  255. struct dp_vdev *vdev2,
  256. struct dp_soc *soc, uint8_t pdev_id)
  257. {
  258. struct dp_soc_be *soc_be = dp_get_be_soc_from_dp_soc(soc);
  259. struct dp_vdev_be *vdev2_be = dp_get_be_vdev_from_dp_vdev(vdev2);
  260. /* return when valid entry exists */
  261. if (vdev2_be->partner_vdev_list[soc_be->mlo_chip_id][pdev_id] !=
  262. CDP_INVALID_VDEV_ID)
  263. return QDF_STATUS_SUCCESS;
  264. if (dp_vdev_get_ref(soc, vdev1, DP_MOD_ID_RX) !=
  265. QDF_STATUS_SUCCESS) {
  266. qdf_info("%pK: unable to get vdev reference vdev %pK vdev_id %u",
  267. soc, vdev1, vdev1->vdev_id);
  268. return QDF_STATUS_E_FAILURE;
  269. }
  270. vdev2_be->partner_vdev_list[soc_be->mlo_chip_id][pdev_id] =
  271. vdev1->vdev_id;
  272. mlo_debug("Add vdev%d to vdev%d list, mlo_chip_id = %d pdev_id = %d\n",
  273. vdev1->vdev_id, vdev2->vdev_id, soc_be->mlo_chip_id, pdev_id);
  274. return QDF_STATUS_SUCCESS;
  275. }
  276. QDF_STATUS dp_update_mlo_ptnr_list(struct cdp_soc_t *soc_hdl,
  277. int8_t partner_vdev_ids[], uint8_t num_vdevs,
  278. uint8_t self_vdev_id)
  279. {
  280. int i, j;
  281. struct dp_soc *self_soc = cdp_soc_t_to_dp_soc(soc_hdl);
  282. struct dp_vdev *self_vdev;
  283. QDF_STATUS ret = QDF_STATUS_SUCCESS;
  284. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(self_soc);
  285. struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt;
  286. if (!dp_mlo)
  287. return QDF_STATUS_E_FAILURE;
  288. self_vdev = dp_vdev_get_ref_by_id(self_soc, self_vdev_id, DP_MOD_ID_RX);
  289. if (!self_vdev)
  290. return QDF_STATUS_E_FAILURE;
  291. /* go through the input vdev id list and if there are partner vdevs,
  292. * - then add the current vdev's id to partner vdev's list using pdev_id and
  293. * increase the reference
  294. * - add partner vdev to self list and increase the reference
  295. */
  296. for (i = 0; i < num_vdevs; i++) {
  297. if (partner_vdev_ids[i] == CDP_INVALID_VDEV_ID)
  298. continue;
  299. for (j = 0; j < WLAN_MAX_MLO_CHIPS; j++) {
  300. struct dp_soc *soc =
  301. dp_mlo_get_soc_ref_by_chip_id(dp_mlo, j);
  302. if (soc) {
  303. struct dp_vdev *vdev;
  304. vdev = dp_vdev_get_ref_by_id(soc,
  305. partner_vdev_ids[i], DP_MOD_ID_RX);
  306. if (vdev) {
  307. if (vdev == self_vdev) {
  308. dp_vdev_unref_delete(soc,
  309. vdev, DP_MOD_ID_RX);
  310. /*dp_soc_unref_delete(soc); */
  311. continue;
  312. }
  313. if (qdf_is_macaddr_equal(
  314. (struct qdf_mac_addr *)self_vdev->mld_mac_addr.raw,
  315. (struct qdf_mac_addr *)vdev->mld_mac_addr.raw)) {
  316. if (dp_mlo_add_ptnr_vdev(self_vdev,
  317. vdev, self_soc,
  318. self_vdev->pdev->pdev_id) !=
  319. QDF_STATUS_SUCCESS) {
  320. dp_err("Unable to add self to partner vdev's list");
  321. dp_vdev_unref_delete(soc,
  322. vdev, DP_MOD_ID_RX);
  323. /* TODO - release soc ref here */
  324. /* dp_soc_unref_delete(soc);*/
  325. ret = QDF_STATUS_E_FAILURE;
  326. goto exit;
  327. }
  328. /* add to self list */
  329. if (dp_mlo_add_ptnr_vdev(vdev, self_vdev, soc,
  330. vdev->pdev->pdev_id) !=
  331. QDF_STATUS_SUCCESS) {
  332. dp_err("Unable to add vdev to self vdev's list");
  333. dp_vdev_unref_delete(self_soc,
  334. vdev, DP_MOD_ID_RX);
  335. /* TODO - release soc ref here */
  336. /* dp_soc_unref_delete(soc);*/
  337. ret = QDF_STATUS_E_FAILURE;
  338. goto exit;
  339. }
  340. }
  341. dp_vdev_unref_delete(soc, vdev,
  342. DP_MOD_ID_RX);
  343. } /* vdev */
  344. /* TODO - release soc ref here */
  345. /* dp_soc_unref_delete(soc); */
  346. } /* soc */
  347. } /* for */
  348. } /* for */
  349. exit:
  350. dp_vdev_unref_delete(self_soc, self_vdev, DP_MOD_ID_RX);
  351. return ret;
  352. }
  353. void dp_clr_mlo_ptnr_list(struct dp_soc *soc, struct dp_vdev *vdev)
  354. {
  355. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  356. struct dp_vdev_be *vdev_be = dp_get_be_vdev_from_dp_vdev(vdev);
  357. struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt;
  358. uint8_t soc_id = be_soc->mlo_chip_id;
  359. uint8_t pdev_id = vdev->pdev->pdev_id;
  360. int i, j;
  361. for (i = 0; i < WLAN_MAX_MLO_CHIPS; i++) {
  362. for (j = 0; j < WLAN_MAX_MLO_LINKS_PER_SOC; j++) {
  363. struct dp_vdev *pr_vdev;
  364. struct dp_soc *pr_soc;
  365. struct dp_soc_be *pr_soc_be;
  366. struct dp_pdev *pr_pdev;
  367. struct dp_vdev_be *pr_vdev_be;
  368. if (vdev_be->partner_vdev_list[i][j] ==
  369. CDP_INVALID_VDEV_ID)
  370. continue;
  371. pr_soc = dp_mlo_get_soc_ref_by_chip_id(dp_mlo, i);
  372. if (!pr_soc)
  373. continue;
  374. pr_soc_be = dp_get_be_soc_from_dp_soc(pr_soc);
  375. pr_vdev = dp_vdev_get_ref_by_id(pr_soc,
  376. vdev_be->partner_vdev_list[i][j],
  377. DP_MOD_ID_RX);
  378. if (!pr_vdev)
  379. continue;
  380. /* release ref and remove self vdev from partner list */
  381. pr_vdev_be = dp_get_be_vdev_from_dp_vdev(pr_vdev);
  382. dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_RX);
  383. pr_vdev_be->partner_vdev_list[soc_id][pdev_id] =
  384. CDP_INVALID_VDEV_ID;
  385. /* release ref and remove partner vdev from self list */
  386. dp_vdev_unref_delete(pr_soc, pr_vdev, DP_MOD_ID_RX);
  387. pr_pdev = pr_vdev->pdev;
  388. vdev_be->partner_vdev_list[pr_soc_be->mlo_chip_id][pr_pdev->pdev_id] =
  389. CDP_INVALID_VDEV_ID;
  390. dp_vdev_unref_delete(pr_soc, pr_vdev, DP_MOD_ID_RX);
  391. }
  392. }
  393. }
  394. static QDF_STATUS
  395. dp_clear_mlo_ptnr_list(struct cdp_soc_t *soc_hdl, uint8_t self_vdev_id)
  396. {
  397. struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
  398. struct dp_vdev *vdev;
  399. vdev = dp_vdev_get_ref_by_id(soc, self_vdev_id, DP_MOD_ID_RX);
  400. if (!vdev)
  401. return QDF_STATUS_E_FAILURE;
  402. dp_clr_mlo_ptnr_list(soc, vdev);
  403. dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_RX);
  404. return QDF_STATUS_SUCCESS;
  405. }
  406. static void dp_mlo_setup_complete(struct cdp_mlo_ctxt *cdp_ml_ctxt)
  407. {
  408. struct dp_mlo_ctxt *mlo_ctxt = cdp_mlo_ctx_to_dp(cdp_ml_ctxt);
  409. int i;
  410. struct dp_soc *soc;
  411. struct dp_soc_be *be_soc;
  412. QDF_STATUS qdf_status;
  413. if (!cdp_ml_ctxt)
  414. return;
  415. for (i = 0; i < WLAN_MAX_MLO_CHIPS; i++) {
  416. soc = dp_mlo_get_soc_ref_by_chip_id(mlo_ctxt, i);
  417. if (!soc)
  418. continue;
  419. be_soc = dp_get_be_soc_from_dp_soc(soc);
  420. qdf_status = dp_partner_soc_rx_hw_cc_init(mlo_ctxt, be_soc);
  421. if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
  422. dp_alert("MLO partner SOC Rx desc CC init failed");
  423. qdf_assert_always(0);
  424. }
  425. }
  426. }
  427. static void dp_mlo_update_delta_tsf2(struct cdp_soc_t *soc_hdl,
  428. uint8_t pdev_id, uint64_t delta_tsf2)
  429. {
  430. struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
  431. struct dp_pdev *pdev;
  432. struct dp_pdev_be *be_pdev;
  433. pdev = dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc,
  434. pdev_id);
  435. if (!pdev) {
  436. dp_err("pdev is NULL for pdev_id %u", pdev_id);
  437. return;
  438. }
  439. be_pdev = dp_get_be_pdev_from_dp_pdev(pdev);
  440. be_pdev->delta_tsf2 = delta_tsf2;
  441. }
  442. static void dp_mlo_update_delta_tqm(struct cdp_soc_t *soc_hdl,
  443. uint64_t delta_tqm)
  444. {
  445. struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
  446. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  447. be_soc->delta_tqm = delta_tqm;
  448. }
  449. static void dp_mlo_update_mlo_ts_offset(struct cdp_soc_t *soc_hdl,
  450. uint64_t offset)
  451. {
  452. struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
  453. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  454. be_soc->mlo_tstamp_offset = offset;
  455. }
  456. static struct cdp_mlo_ops dp_mlo_ops = {
  457. .mlo_soc_setup = dp_mlo_soc_setup,
  458. .mlo_soc_teardown = dp_mlo_soc_teardown,
  459. .update_mlo_ptnr_list = dp_update_mlo_ptnr_list,
  460. .clear_mlo_ptnr_list = dp_clear_mlo_ptnr_list,
  461. .mlo_setup_complete = dp_mlo_setup_complete,
  462. .mlo_update_delta_tsf2 = dp_mlo_update_delta_tsf2,
  463. .mlo_update_delta_tqm = dp_mlo_update_delta_tqm,
  464. .mlo_update_mlo_ts_offset = dp_mlo_update_mlo_ts_offset,
  465. .mlo_ctxt_attach = dp_mlo_ctxt_attach_wifi3,
  466. .mlo_ctxt_detach = dp_mlo_ctxt_detach_wifi3,
  467. };
  468. void dp_soc_mlo_fill_params(struct dp_soc *soc,
  469. struct cdp_soc_attach_params *params)
  470. {
  471. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  472. if (!params->mlo_enabled) {
  473. dp_warn("MLO not enabled on SOC");
  474. return;
  475. }
  476. be_soc->mlo_chip_id = params->mlo_chip_id;
  477. be_soc->ml_ctxt = cdp_mlo_ctx_to_dp(params->ml_context);
  478. be_soc->mlo_enabled = 1;
  479. soc->cdp_soc.ops->mlo_ops = &dp_mlo_ops;
  480. }
  481. void dp_mlo_update_link_to_pdev_map(struct dp_soc *soc, struct dp_pdev *pdev)
  482. {
  483. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  484. struct dp_pdev_be *be_pdev = dp_get_be_pdev_from_dp_pdev(pdev);
  485. struct dp_mlo_ctxt *ml_ctxt = be_soc->ml_ctxt;
  486. uint8_t link_id;
  487. if (!be_soc->mlo_enabled)
  488. return;
  489. if (!ml_ctxt)
  490. return;
  491. link_id = be_pdev->mlo_link_id;
  492. if (link_id < WLAN_MAX_MLO_CHIPS * WLAN_MAX_MLO_LINKS_PER_SOC) {
  493. if (!ml_ctxt->link_to_pdev_map[link_id])
  494. ml_ctxt->link_to_pdev_map[link_id] = be_pdev;
  495. else
  496. dp_alert("Attempt to update existing map for link %u",
  497. link_id);
  498. }
  499. }
  500. void dp_mlo_update_link_to_pdev_unmap(struct dp_soc *soc, struct dp_pdev *pdev)
  501. {
  502. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  503. struct dp_pdev_be *be_pdev = dp_get_be_pdev_from_dp_pdev(pdev);
  504. struct dp_mlo_ctxt *ml_ctxt = be_soc->ml_ctxt;
  505. uint8_t link_id;
  506. if (!be_soc->mlo_enabled)
  507. return;
  508. if (!ml_ctxt)
  509. return;
  510. link_id = be_pdev->mlo_link_id;
  511. if (link_id < WLAN_MAX_MLO_CHIPS * WLAN_MAX_MLO_LINKS_PER_SOC)
  512. ml_ctxt->link_to_pdev_map[link_id] = NULL;
  513. }
  514. static struct dp_pdev_be *
  515. dp_mlo_get_be_pdev_from_link_id(struct dp_mlo_ctxt *ml_ctxt, uint8_t link_id)
  516. {
  517. if (link_id < WLAN_MAX_MLO_CHIPS * WLAN_MAX_MLO_LINKS_PER_SOC)
  518. return ml_ctxt->link_to_pdev_map[link_id];
  519. return NULL;
  520. }
  521. void dp_pdev_mlo_fill_params(struct dp_pdev *pdev,
  522. struct cdp_pdev_attach_params *params)
  523. {
  524. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(pdev->soc);
  525. struct dp_pdev_be *be_pdev = dp_get_be_pdev_from_dp_pdev(pdev);
  526. if (!be_soc->mlo_enabled) {
  527. dp_info("MLO not enabled on SOC");
  528. return;
  529. }
  530. be_pdev->mlo_link_id = params->mlo_link_id;
  531. }
  532. void dp_mlo_partner_chips_map(struct dp_soc *soc,
  533. struct dp_peer *peer,
  534. uint16_t peer_id)
  535. {
  536. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  537. struct dp_mlo_ctxt *mlo_ctxt = NULL;
  538. bool is_ml_peer_id =
  539. HTT_RX_PEER_META_DATA_V1_ML_PEER_VALID_GET(peer_id);
  540. uint8_t chip_id;
  541. struct dp_soc *temp_soc;
  542. /* for non ML peer dont map on partner chips*/
  543. if (!is_ml_peer_id)
  544. return;
  545. mlo_ctxt = be_soc->ml_ctxt;
  546. if (!mlo_ctxt)
  547. return;
  548. qdf_spin_lock_bh(&mlo_ctxt->ml_soc_list_lock);
  549. for (chip_id = 0; chip_id < DP_MAX_MLO_CHIPS; chip_id++) {
  550. temp_soc = mlo_ctxt->ml_soc_list[chip_id];
  551. if (!temp_soc)
  552. continue;
  553. /* skip if this is current soc */
  554. if (temp_soc == soc)
  555. continue;
  556. dp_peer_find_id_to_obj_add(temp_soc, peer, peer_id);
  557. }
  558. qdf_spin_unlock_bh(&mlo_ctxt->ml_soc_list_lock);
  559. }
  560. qdf_export_symbol(dp_mlo_partner_chips_map);
  561. void dp_mlo_partner_chips_unmap(struct dp_soc *soc,
  562. uint16_t peer_id)
  563. {
  564. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  565. struct dp_mlo_ctxt *mlo_ctxt = be_soc->ml_ctxt;
  566. bool is_ml_peer_id =
  567. HTT_RX_PEER_META_DATA_V1_ML_PEER_VALID_GET(peer_id);
  568. uint8_t chip_id;
  569. struct dp_soc *temp_soc;
  570. if (!is_ml_peer_id)
  571. return;
  572. if (!mlo_ctxt)
  573. return;
  574. qdf_spin_lock_bh(&mlo_ctxt->ml_soc_list_lock);
  575. for (chip_id = 0; chip_id < DP_MAX_MLO_CHIPS; chip_id++) {
  576. temp_soc = mlo_ctxt->ml_soc_list[chip_id];
  577. if (!temp_soc)
  578. continue;
  579. /* skip if this is current soc */
  580. if (temp_soc == soc)
  581. continue;
  582. dp_peer_find_id_to_obj_remove(temp_soc, peer_id);
  583. }
  584. qdf_spin_unlock_bh(&mlo_ctxt->ml_soc_list_lock);
  585. }
  586. qdf_export_symbol(dp_mlo_partner_chips_unmap);
  587. uint8_t dp_mlo_get_chip_id(struct dp_soc *soc)
  588. {
  589. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  590. return be_soc->mlo_chip_id;
  591. }
  592. qdf_export_symbol(dp_mlo_get_chip_id);
  593. struct dp_peer *
  594. dp_link_peer_hash_find_by_chip_id(struct dp_soc *soc,
  595. uint8_t *peer_mac_addr,
  596. int mac_addr_is_aligned,
  597. uint8_t vdev_id,
  598. uint8_t chip_id,
  599. enum dp_mod_id mod_id)
  600. {
  601. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  602. struct dp_mlo_ctxt *mlo_ctxt = be_soc->ml_ctxt;
  603. struct dp_soc *link_peer_soc = NULL;
  604. struct dp_peer *peer = NULL;
  605. if (!mlo_ctxt)
  606. return NULL;
  607. link_peer_soc = dp_mlo_get_soc_ref_by_chip_id(mlo_ctxt, chip_id);
  608. if (!link_peer_soc)
  609. return NULL;
  610. peer = dp_peer_find_hash_find(link_peer_soc, peer_mac_addr,
  611. mac_addr_is_aligned, vdev_id,
  612. mod_id);
  613. qdf_atomic_dec(&link_peer_soc->ref_count);
  614. return peer;
  615. }
  616. qdf_export_symbol(dp_link_peer_hash_find_by_chip_id);
  617. void dp_mlo_get_rx_hash_key(struct dp_soc *soc,
  618. struct cdp_lro_hash_config *lro_hash)
  619. {
  620. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  621. struct dp_mlo_ctxt *ml_ctxt = be_soc->ml_ctxt;
  622. if (!be_soc->mlo_enabled || !ml_ctxt)
  623. return dp_get_rx_hash_key_bytes(lro_hash);
  624. qdf_mem_copy(lro_hash->toeplitz_hash_ipv4, ml_ctxt->toeplitz_hash_ipv4,
  625. (sizeof(lro_hash->toeplitz_hash_ipv4[0]) *
  626. LRO_IPV4_SEED_ARR_SZ));
  627. qdf_mem_copy(lro_hash->toeplitz_hash_ipv6, ml_ctxt->toeplitz_hash_ipv6,
  628. (sizeof(lro_hash->toeplitz_hash_ipv6[0]) *
  629. LRO_IPV6_SEED_ARR_SZ));
  630. }
  631. struct dp_soc *
  632. dp_rx_replensih_soc_get(struct dp_soc *soc, uint8_t chip_id)
  633. {
  634. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  635. struct dp_mlo_ctxt *mlo_ctxt = be_soc->ml_ctxt;
  636. struct dp_soc *replenish_soc;
  637. if (!be_soc->mlo_enabled || !mlo_ctxt)
  638. return soc;
  639. if (be_soc->mlo_chip_id == chip_id)
  640. return soc;
  641. replenish_soc = dp_mlo_get_soc_ref_by_chip_id(mlo_ctxt, chip_id);
  642. if (qdf_unlikely(!replenish_soc)) {
  643. dp_alert("replenish SOC is NULL");
  644. qdf_assert_always(0);
  645. }
  646. return replenish_soc;
  647. }
  648. uint8_t dp_soc_get_num_soc_be(struct dp_soc *soc)
  649. {
  650. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  651. struct dp_mlo_ctxt *mlo_ctxt = be_soc->ml_ctxt;
  652. if (!be_soc->mlo_enabled || !mlo_ctxt)
  653. return 1;
  654. return mlo_ctxt->ml_soc_cnt;
  655. }
  656. struct dp_soc *
  657. dp_soc_get_by_idle_bm_id(struct dp_soc *soc, uint8_t idle_bm_id)
  658. {
  659. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  660. struct dp_mlo_ctxt *mlo_ctxt = be_soc->ml_ctxt;
  661. struct dp_soc *partner_soc = NULL;
  662. uint8_t chip_id;
  663. if (!be_soc->mlo_enabled || !mlo_ctxt)
  664. return soc;
  665. for (chip_id = 0; chip_id < WLAN_MAX_MLO_CHIPS; chip_id++) {
  666. partner_soc = dp_mlo_get_soc_ref_by_chip_id(mlo_ctxt, chip_id);
  667. if (!partner_soc)
  668. continue;
  669. if (partner_soc->idle_link_bm_id == idle_bm_id)
  670. return partner_soc;
  671. }
  672. return NULL;
  673. }
  674. #ifdef WLAN_MCAST_MLO
  675. void dp_mlo_iter_ptnr_soc(struct dp_soc_be *be_soc,
  676. dp_ptnr_soc_iter_func func,
  677. void *arg)
  678. {
  679. int i = 0;
  680. struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt;
  681. for (i = 0; i < WLAN_MAX_MLO_CHIPS ; i++) {
  682. struct dp_soc *ptnr_soc =
  683. dp_mlo_get_soc_ref_by_chip_id(dp_mlo, i);
  684. if (!ptnr_soc)
  685. continue;
  686. (*func)(ptnr_soc, arg);
  687. }
  688. }
  689. qdf_export_symbol(dp_mlo_iter_ptnr_soc);
  690. void dp_mcast_mlo_iter_ptnr_vdev(struct dp_soc_be *be_soc,
  691. struct dp_vdev_be *be_vdev,
  692. dp_ptnr_vdev_iter_func func,
  693. void *arg,
  694. enum dp_mod_id mod_id)
  695. {
  696. int i = 0;
  697. int j = 0;
  698. struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt;
  699. for (i = 0; i < WLAN_MAX_MLO_CHIPS ; i++) {
  700. struct dp_soc *ptnr_soc =
  701. dp_mlo_get_soc_ref_by_chip_id(dp_mlo, i);
  702. if (!ptnr_soc)
  703. continue;
  704. for (j = 0 ; j < WLAN_MAX_MLO_LINKS_PER_SOC ; j++) {
  705. struct dp_vdev *ptnr_vdev;
  706. ptnr_vdev = dp_vdev_get_ref_by_id(
  707. ptnr_soc,
  708. be_vdev->partner_vdev_list[i][j],
  709. mod_id);
  710. if (!ptnr_vdev)
  711. continue;
  712. (*func)(be_vdev, ptnr_vdev, arg);
  713. dp_vdev_unref_delete(ptnr_vdev->pdev->soc,
  714. ptnr_vdev,
  715. mod_id);
  716. }
  717. }
  718. }
  719. qdf_export_symbol(dp_mcast_mlo_iter_ptnr_vdev);
  720. struct dp_vdev *dp_mlo_get_mcast_primary_vdev(struct dp_soc_be *be_soc,
  721. struct dp_vdev_be *be_vdev,
  722. enum dp_mod_id mod_id)
  723. {
  724. int i = 0;
  725. int j = 0;
  726. struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt;
  727. for (i = 0; i < WLAN_MAX_MLO_CHIPS ; i++) {
  728. struct dp_soc *ptnr_soc =
  729. dp_mlo_get_soc_ref_by_chip_id(dp_mlo, i);
  730. if (!ptnr_soc)
  731. continue;
  732. for (j = 0 ; j < WLAN_MAX_MLO_LINKS_PER_SOC ; j++) {
  733. struct dp_vdev *ptnr_vdev = NULL;
  734. struct dp_vdev_be *be_ptnr_vdev = NULL;
  735. ptnr_vdev = dp_vdev_get_ref_by_id(
  736. ptnr_soc,
  737. be_vdev->partner_vdev_list[i][j],
  738. mod_id);
  739. if (!ptnr_vdev)
  740. continue;
  741. be_ptnr_vdev = dp_get_be_vdev_from_dp_vdev(ptnr_vdev);
  742. if (be_ptnr_vdev->mcast_primary)
  743. return ptnr_vdev;
  744. dp_vdev_unref_delete(be_ptnr_vdev->vdev.pdev->soc,
  745. &be_ptnr_vdev->vdev,
  746. mod_id);
  747. }
  748. }
  749. return NULL;
  750. }
  751. qdf_export_symbol(dp_mlo_get_mcast_primary_vdev);
  752. #endif
  753. static inline uint64_t dp_mlo_get_mlo_ts_offset(struct dp_pdev_be *be_pdev)
  754. {
  755. struct dp_soc *soc;
  756. struct dp_pdev *pdev;
  757. struct dp_soc_be *be_soc;
  758. uint32_t mlo_offset;
  759. pdev = &be_pdev->pdev;
  760. soc = pdev->soc;
  761. be_soc = dp_get_be_soc_from_dp_soc(soc);
  762. mlo_offset = be_soc->mlo_tstamp_offset;
  763. return mlo_offset;
  764. }
  765. int32_t dp_mlo_get_delta_tsf2_wrt_mlo_offset(struct dp_soc *soc,
  766. uint8_t hw_link_id)
  767. {
  768. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  769. struct dp_mlo_ctxt *ml_ctxt = be_soc->ml_ctxt;
  770. struct dp_pdev_be *be_pdev;
  771. int32_t delta_tsf2_mlo_offset;
  772. int32_t mlo_offset, delta_tsf2;
  773. if (!ml_ctxt)
  774. return 0;
  775. be_pdev = dp_mlo_get_be_pdev_from_link_id(ml_ctxt, hw_link_id);
  776. if (!be_pdev)
  777. return 0;
  778. mlo_offset = dp_mlo_get_mlo_ts_offset(be_pdev);
  779. delta_tsf2 = be_pdev->delta_tsf2;
  780. delta_tsf2_mlo_offset = mlo_offset - delta_tsf2;
  781. return delta_tsf2_mlo_offset;
  782. }
  783. int32_t dp_mlo_get_delta_tqm_wrt_mlo_offset(struct dp_soc *soc)
  784. {
  785. struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
  786. int32_t delta_tqm_mlo_offset;
  787. int32_t mlo_offset, delta_tqm;
  788. mlo_offset = be_soc->mlo_tstamp_offset;
  789. delta_tqm = be_soc->delta_tqm;
  790. delta_tqm_mlo_offset = mlo_offset - delta_tqm;
  791. return delta_tqm_mlo_offset;
  792. }