wmi_unified_11be_tlv.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. /*
  2. * Copyright (c) 2021, The Linux Foundation. All rights reserved.
  3. * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include <osdep.h>
  18. #include "wmi.h"
  19. #include "wmi_unified_priv.h"
  20. #include "wmi_unified_api.h"
  21. #ifdef WLAN_MLO_MULTI_CHIP
  22. #include "wmi_unified_11be_setup_api.h"
  23. #endif
  24. #include "wmi_unified_11be_tlv.h"
  25. size_t vdev_create_mlo_params_size(void)
  26. {
  27. return sizeof(wmi_vdev_create_mlo_params) + WMI_TLV_HDR_SIZE;
  28. }
  29. uint8_t *vdev_create_add_mlo_params(uint8_t *buf_ptr,
  30. struct vdev_create_params *param)
  31. {
  32. wmi_vdev_create_mlo_params *mlo_params;
  33. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  34. sizeof(wmi_vdev_create_mlo_params));
  35. buf_ptr += sizeof(uint32_t);
  36. mlo_params = (wmi_vdev_create_mlo_params *)buf_ptr;
  37. WMITLV_SET_HDR(&mlo_params->tlv_header,
  38. WMITLV_TAG_STRUC_wmi_vdev_create_mlo_params,
  39. WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_create_mlo_params));
  40. WMI_CHAR_ARRAY_TO_MAC_ADDR(param->mlo_mac, &mlo_params->mld_macaddr);
  41. wmi_debug("MLD Addr = "QDF_MAC_ADDR_FMT,
  42. QDF_MAC_ADDR_REF(param->mlo_mac));
  43. return buf_ptr + sizeof(wmi_vdev_create_mlo_params);
  44. }
  45. size_t vdev_start_mlo_params_size(struct vdev_start_params *req)
  46. {
  47. size_t vdev_start_mlo_size;
  48. vdev_start_mlo_size = sizeof(wmi_vdev_start_mlo_params) +
  49. WMI_TLV_HDR_SIZE +
  50. (req->mlo_partner.num_links *
  51. sizeof(wmi_partner_link_params)) +
  52. WMI_TLV_HDR_SIZE;
  53. return vdev_start_mlo_size;
  54. }
  55. #ifdef WLAN_MCAST_MLO
  56. static void vdev_start_add_mlo_mcast_params(uint32_t *mlo_flags,
  57. struct vdev_start_params *req)
  58. {
  59. WMI_MLO_FLAGS_SET_MCAST_VDEV(*mlo_flags,
  60. req->mlo_flags.mlo_mcast_vdev);
  61. }
  62. #else
  63. #define vdev_start_add_mlo_mcast_params(mlo_flags, req)
  64. #endif
  65. uint8_t *vdev_start_add_mlo_params(uint8_t *buf_ptr,
  66. struct vdev_start_params *req)
  67. {
  68. wmi_vdev_start_mlo_params *mlo_params;
  69. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  70. sizeof(wmi_vdev_start_mlo_params));
  71. buf_ptr += sizeof(uint32_t);
  72. mlo_params = (wmi_vdev_start_mlo_params *)buf_ptr;
  73. WMITLV_SET_HDR(&mlo_params->tlv_header,
  74. WMITLV_TAG_STRUC_wmi_vdev_start_mlo_params,
  75. WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_start_mlo_params));
  76. mlo_params->mlo_flags.mlo_flags = 0;
  77. WMI_MLO_FLAGS_SET_ENABLED(mlo_params->mlo_flags.mlo_flags,
  78. req->mlo_flags.mlo_enabled);
  79. WMI_MLO_FLAGS_SET_ASSOC_LINK(mlo_params->mlo_flags.mlo_flags,
  80. req->mlo_flags.mlo_assoc_link);
  81. vdev_start_add_mlo_mcast_params(&mlo_params->mlo_flags.mlo_flags,
  82. req);
  83. return buf_ptr + sizeof(wmi_vdev_start_mlo_params);
  84. }
  85. uint8_t *vdev_start_add_ml_partner_links(uint8_t *buf_ptr,
  86. struct vdev_start_params *req)
  87. {
  88. wmi_partner_link_params *ml_partner_link;
  89. struct mlo_vdev_start_partner_links *req_partner;
  90. uint8_t i;
  91. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  92. (req->mlo_partner.num_links *
  93. sizeof(wmi_partner_link_params)));
  94. buf_ptr += sizeof(uint32_t);
  95. req_partner = &req->mlo_partner;
  96. ml_partner_link = (wmi_partner_link_params *)buf_ptr;
  97. for (i = 0; i < req->mlo_partner.num_links; i++) {
  98. WMITLV_SET_HDR(&ml_partner_link->tlv_header,
  99. WMITLV_TAG_STRUC_wmi_partner_link_params,
  100. WMITLV_GET_STRUCT_TLVLEN(wmi_partner_link_params));
  101. ml_partner_link->vdev_id = req_partner->partner_info[i].vdev_id;
  102. ml_partner_link->hw_link_id =
  103. req_partner->partner_info[i].hw_mld_link_id;
  104. WMI_CHAR_ARRAY_TO_MAC_ADDR(req_partner->partner_info[i].mac_addr,
  105. &ml_partner_link->vdev_macaddr);
  106. ml_partner_link++;
  107. }
  108. return buf_ptr +
  109. (req->mlo_partner.num_links *
  110. sizeof(wmi_partner_link_params));
  111. }
  112. uint8_t *bcn_tmpl_add_ml_partner_links(uint8_t *buf_ptr,
  113. struct beacon_tmpl_params *param)
  114. {
  115. wmi_bcn_tmpl_ml_params *ml_partner_link;
  116. struct mlo_bcn_templ_partner_links *ml_bcn_tmpl;
  117. uint8_t i;
  118. if (param->mlo_partner.num_links > WLAN_UMAC_MLO_MAX_VDEVS) {
  119. wmi_err("mlo_partner.num_link(%d) are greater than supported partner links(%d)",
  120. param->mlo_partner.num_links, WLAN_UMAC_MLO_MAX_VDEVS);
  121. return buf_ptr;
  122. }
  123. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  124. (param->mlo_partner.num_links *
  125. sizeof(wmi_bcn_tmpl_ml_params)));
  126. buf_ptr += sizeof(uint32_t);
  127. ml_bcn_tmpl = &param->mlo_partner;
  128. ml_partner_link = (wmi_bcn_tmpl_ml_params *)buf_ptr;
  129. for (i = 0; i < ml_bcn_tmpl->num_links; i++) {
  130. WMITLV_SET_HDR(&ml_partner_link->tlv_header,
  131. WMITLV_TAG_STRUC_wmi_bcn_tmpl_ml_params,
  132. WMITLV_GET_STRUCT_TLVLEN(wmi_bcn_tmpl_ml_params)
  133. );
  134. ml_partner_link->vdev_id = ml_bcn_tmpl->partner_info[i].vdev_id;
  135. ml_partner_link->hw_link_id =
  136. ml_bcn_tmpl->partner_info[i].hw_link_id;
  137. ml_partner_link->beacon_interval =
  138. ml_bcn_tmpl->partner_info[i].beacon_interval;
  139. ml_partner_link->csa_switch_count_offset =
  140. ml_bcn_tmpl->partner_info[i].csa_switch_count_offset;
  141. ml_partner_link->ext_csa_switch_count_offset =
  142. ml_bcn_tmpl->partner_info[i].ext_csa_switch_count_offset;
  143. ml_partner_link->per_sta_profile_offset =
  144. ml_bcn_tmpl->partner_info[i].per_sta_profile_offset;
  145. ml_partner_link->quiet_ie_offset =
  146. ml_bcn_tmpl->partner_info[i].quiet_ie_offset;
  147. ml_partner_link->is_other_ie_present =
  148. ml_bcn_tmpl->partner_info[i].is_other_ie_present;
  149. ml_partner_link++;
  150. }
  151. return buf_ptr +
  152. (param->mlo_partner.num_links *
  153. sizeof(wmi_bcn_tmpl_ml_params));
  154. }
  155. size_t peer_create_mlo_params_size(struct peer_create_params *req)
  156. {
  157. return sizeof(wmi_peer_create_mlo_params) + WMI_TLV_HDR_SIZE;
  158. }
  159. uint8_t *peer_create_add_mlo_params(uint8_t *buf_ptr,
  160. struct peer_create_params *req)
  161. {
  162. wmi_peer_create_mlo_params *mlo_params;
  163. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  164. sizeof(wmi_peer_create_mlo_params));
  165. buf_ptr += sizeof(uint32_t);
  166. mlo_params = (wmi_peer_create_mlo_params *)buf_ptr;
  167. WMITLV_SET_HDR(&mlo_params->tlv_header,
  168. WMITLV_TAG_STRUC_wmi_peer_create_mlo_params,
  169. WMITLV_GET_STRUCT_TLVLEN(wmi_peer_create_mlo_params));
  170. mlo_params->mlo_flags.mlo_flags = 0;
  171. WMI_MLO_FLAGS_SET_ENABLED(mlo_params->mlo_flags.mlo_flags,
  172. req->mlo_enabled);
  173. return buf_ptr + sizeof(wmi_peer_create_mlo_params);
  174. }
  175. size_t peer_assoc_mlo_params_size(struct peer_assoc_params *req)
  176. {
  177. size_t peer_assoc_mlo_size = sizeof(wmi_peer_assoc_mlo_params) +
  178. WMI_TLV_HDR_SIZE +
  179. (req->ml_links.num_links *
  180. sizeof(wmi_peer_assoc_mlo_partner_link_params)) +
  181. WMI_TLV_HDR_SIZE;
  182. return peer_assoc_mlo_size;
  183. }
  184. uint8_t *peer_assoc_add_mlo_params(uint8_t *buf_ptr,
  185. struct peer_assoc_params *req)
  186. {
  187. wmi_peer_assoc_mlo_params *mlo_params;
  188. /* Add WMI peer assoc mlo params */
  189. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  190. sizeof(wmi_peer_assoc_mlo_params));
  191. buf_ptr += sizeof(uint32_t);
  192. mlo_params = (wmi_peer_assoc_mlo_params *)buf_ptr;
  193. WMITLV_SET_HDR(&mlo_params->tlv_header,
  194. WMITLV_TAG_STRUC_wmi_peer_assoc_mlo_params,
  195. WMITLV_GET_STRUCT_TLVLEN(wmi_peer_assoc_mlo_params));
  196. mlo_params->mlo_flags.mlo_flags = 0;
  197. WMI_MLO_FLAGS_SET_ENABLED(mlo_params->mlo_flags.mlo_flags,
  198. req->mlo_params.mlo_enabled);
  199. WMI_MLO_FLAGS_SET_ASSOC_LINK(mlo_params->mlo_flags.mlo_flags,
  200. req->mlo_params.mlo_assoc_link);
  201. WMI_MLO_FLAGS_SET_PRIMARY_UMAC(mlo_params->mlo_flags.mlo_flags,
  202. req->mlo_params.mlo_primary_umac);
  203. WMI_MLO_FLAGS_SET_LINK_INDEX_VALID(mlo_params->mlo_flags.mlo_flags,
  204. req->mlo_params.mlo_logical_link_index_valid);
  205. WMI_MLO_FLAGS_SET_PEER_ID_VALID(mlo_params->mlo_flags.mlo_flags,
  206. req->mlo_params.mlo_peer_id_valid);
  207. WMI_CHAR_ARRAY_TO_MAC_ADDR(req->mlo_params.mld_mac,
  208. &mlo_params->mld_macaddr);
  209. mlo_params->logical_link_index = req->mlo_params.logical_link_index;
  210. mlo_params->mld_peer_id = req->mlo_params.ml_peer_id;
  211. return buf_ptr + sizeof(wmi_peer_assoc_mlo_params);
  212. }
  213. uint8_t *peer_assoc_add_ml_partner_links(uint8_t *buf_ptr,
  214. struct peer_assoc_params *req)
  215. {
  216. wmi_peer_assoc_mlo_partner_link_params *ml_partner_link;
  217. struct ml_partner_info *partner_info;
  218. uint8_t i;
  219. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  220. (req->ml_links.num_links *
  221. sizeof(wmi_peer_assoc_mlo_partner_link_params)));
  222. buf_ptr += sizeof(uint32_t);
  223. ml_partner_link = (wmi_peer_assoc_mlo_partner_link_params *)buf_ptr;
  224. partner_info = req->ml_links.partner_info;
  225. for (i = 0; i < req->ml_links.num_links; i++) {
  226. WMITLV_SET_HDR(&ml_partner_link->tlv_header,
  227. WMITLV_TAG_STRUC_wmi_peer_assoc_mlo_partner_link_params,
  228. WMITLV_GET_STRUCT_TLVLEN(wmi_peer_assoc_mlo_partner_link_params));
  229. ml_partner_link->vdev_id = partner_info[i].vdev_id;
  230. ml_partner_link->hw_mld_link_id = partner_info[i].hw_mld_link_id;
  231. ml_partner_link++;
  232. }
  233. return buf_ptr +
  234. (req->ml_links.num_links *
  235. sizeof(wmi_peer_assoc_mlo_partner_link_params));
  236. }
  237. /**
  238. * force_mode_host_to_fw() - translate force mode for MLO link set active
  239. * command
  240. * @host_mode: force mode defined by host
  241. * @fw_mode: buffer to store force mode defined by FW
  242. *
  243. * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL otherwise
  244. */
  245. static inline QDF_STATUS
  246. force_mode_host_to_fw(enum mlo_link_force_mode host_mode,
  247. WMI_MLO_LINK_FORCE_MODE *fw_mode)
  248. {
  249. switch (host_mode) {
  250. case MLO_LINK_FORCE_MODE_ACTIVE:
  251. *fw_mode = WMI_MLO_LINK_FORCE_ACTIVE;
  252. break;
  253. case MLO_LINK_FORCE_MODE_INACTIVE:
  254. *fw_mode = WMI_MLO_LINK_FORCE_INACTIVE;
  255. break;
  256. case MLO_LINK_FORCE_MODE_ACTIVE_NUM:
  257. *fw_mode = WMI_MLO_LINK_FORCE_ACTIVE_LINK_NUM;
  258. break;
  259. case MLO_LINK_FORCE_MODE_INACTIVE_NUM:
  260. *fw_mode = WMI_MLO_LINK_FORCE_INACTIVE_LINK_NUM;
  261. break;
  262. case MLO_LINK_FORCE_MODE_NO_FORCE:
  263. *fw_mode = WMI_MLO_LINK_NO_FORCE;
  264. break;
  265. default:
  266. wmi_err("Invalid force mode: %d", host_mode);
  267. return QDF_STATUS_E_INVAL;
  268. }
  269. return QDF_STATUS_SUCCESS;
  270. }
  271. /**
  272. * force_reason_host_to_fw() - translate force reason for MLO link set active
  273. * command
  274. * @host_reason: force reason defined by host
  275. * @fw_reason: buffer to store force reason defined by FW
  276. *
  277. * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL otherwise
  278. */
  279. static inline QDF_STATUS
  280. force_reason_host_to_fw(enum mlo_link_force_reason host_reason,
  281. WMI_MLO_LINK_FORCE_REASON *fw_reason)
  282. {
  283. switch (host_reason) {
  284. case MLO_LINK_FORCE_REASON_CONNECT:
  285. *fw_reason = WMI_MLO_LINK_FORCE_REASON_NEW_CONNECT;
  286. break;
  287. case MLO_LINK_FORCE_REASON_DISCONNECT:
  288. *fw_reason = WMI_MLO_LINK_FORCE_REASON_NEW_DISCONNECT;
  289. break;
  290. default:
  291. wmi_err("Invalid force reason: %d", host_reason);
  292. return QDF_STATUS_E_INVAL;
  293. }
  294. return QDF_STATUS_SUCCESS;
  295. }
  296. /**
  297. * send_mlo_link_set_active_cmd_tlv() - send mlo link set active command
  298. * @wmi_handle: wmi handle
  299. * @param: Pointer to mlo link set active param
  300. *
  301. * Return: QDF_STATUS_SUCCESS for success or QDF_STATUS_E_* for error
  302. */
  303. static QDF_STATUS
  304. send_mlo_link_set_active_cmd_tlv(wmi_unified_t wmi_handle,
  305. struct mlo_link_set_active_param *param)
  306. {
  307. QDF_STATUS status;
  308. wmi_mlo_link_set_active_cmd_fixed_param *cmd;
  309. wmi_mlo_set_active_link_number_param *link_num_param;
  310. uint32_t *vdev_bitmap;
  311. uint32_t num_link_num_param = 0, num_vdev_bitmap = 0, tlv_len;
  312. wmi_buf_t buf;
  313. uint8_t *buf_ptr;
  314. uint32_t len;
  315. int i;
  316. WMITLV_TAG_ID tag_id;
  317. WMI_MLO_LINK_FORCE_MODE force_mode;
  318. WMI_MLO_LINK_FORCE_REASON force_reason;
  319. if (!param->num_vdev_bitmap && !param->num_link_entry) {
  320. wmi_err("No entry is provided vdev bit map %d link entry %d",
  321. param->num_vdev_bitmap,
  322. param->num_link_entry);
  323. return QDF_STATUS_E_INVAL;
  324. }
  325. status = force_mode_host_to_fw(param->force_mode, &force_mode);
  326. if (QDF_IS_STATUS_ERROR(status))
  327. return QDF_STATUS_E_INVAL;
  328. status = force_reason_host_to_fw(param->reason, &force_reason);
  329. if (QDF_IS_STATUS_ERROR(status))
  330. return QDF_STATUS_E_INVAL;
  331. switch (force_mode) {
  332. case WMI_MLO_LINK_FORCE_ACTIVE_LINK_NUM:
  333. case WMI_MLO_LINK_FORCE_INACTIVE_LINK_NUM:
  334. num_link_num_param = param->num_link_entry;
  335. /* fallthrough */
  336. case WMI_MLO_LINK_FORCE_ACTIVE:
  337. case WMI_MLO_LINK_FORCE_INACTIVE:
  338. case WMI_MLO_LINK_NO_FORCE:
  339. num_vdev_bitmap = param->num_vdev_bitmap;
  340. break;
  341. }
  342. len = sizeof(*cmd) +
  343. WMI_TLV_HDR_SIZE + sizeof(*link_num_param) * num_link_num_param +
  344. WMI_TLV_HDR_SIZE + sizeof(*vdev_bitmap) * num_vdev_bitmap;
  345. buf = wmi_buf_alloc(wmi_handle, len);
  346. if (!buf)
  347. return QDF_STATUS_E_NOMEM;
  348. buf_ptr = (uint8_t *)wmi_buf_data(buf);
  349. cmd = (wmi_mlo_link_set_active_cmd_fixed_param *)buf_ptr;
  350. tlv_len = WMITLV_GET_STRUCT_TLVLEN
  351. (wmi_mlo_link_set_active_cmd_fixed_param);
  352. tag_id = WMITLV_TAG_STRUC_wmi_mlo_link_set_active_cmd_fixed_param;
  353. WMITLV_SET_HDR(&cmd->tlv_header, tag_id, tlv_len);
  354. cmd->force_mode = force_mode;
  355. cmd->reason = force_reason;
  356. wmi_debug("mode %d reason %d num_link_num_param %d num_vdev_bitmap %d",
  357. cmd->force_mode, cmd->reason, num_link_num_param,
  358. num_vdev_bitmap);
  359. buf_ptr += sizeof(*cmd);
  360. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  361. sizeof(*link_num_param) * num_link_num_param);
  362. buf_ptr += WMI_TLV_HDR_SIZE;
  363. if (num_link_num_param) {
  364. link_num_param =
  365. (wmi_mlo_set_active_link_number_param *)buf_ptr;
  366. tlv_len = WMITLV_GET_STRUCT_TLVLEN
  367. (wmi_mlo_set_active_link_number_param);
  368. for (i = 0; i < num_link_num_param; i++) {
  369. WMITLV_SET_HDR(&link_num_param->tlv_header, 0, tlv_len);
  370. link_num_param->num_of_link =
  371. param->link_num[i].num_of_link;
  372. link_num_param->vdev_type =
  373. param->link_num[i].vdev_type;
  374. link_num_param->vdev_subtype =
  375. param->link_num[i].vdev_subtype;
  376. link_num_param->home_freq =
  377. param->link_num[i].home_freq;
  378. wmi_debug("entry[%d]: num_of_link %d vdev type %d subtype %d freq %d",
  379. i, link_num_param->num_of_link,
  380. link_num_param->vdev_type,
  381. link_num_param->vdev_subtype,
  382. link_num_param->home_freq);
  383. link_num_param++;
  384. }
  385. buf_ptr += sizeof(*link_num_param) * num_link_num_param;
  386. }
  387. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
  388. sizeof(*vdev_bitmap) * num_vdev_bitmap);
  389. buf_ptr += WMI_TLV_HDR_SIZE;
  390. if (num_vdev_bitmap) {
  391. vdev_bitmap = (A_UINT32 *)(buf_ptr);
  392. for (i = 0; i < num_vdev_bitmap; i++) {
  393. vdev_bitmap[i] = param->vdev_bitmap[i];
  394. wmi_debug("entry[%d]: vdev_id_bitmap 0x%x ",
  395. i, vdev_bitmap[i]);
  396. }
  397. buf_ptr += sizeof(*vdev_bitmap) * num_vdev_bitmap;
  398. }
  399. wmi_mtrace(WMI_MLO_LINK_SET_ACTIVE_CMDID, 0, cmd->force_mode);
  400. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  401. WMI_MLO_LINK_SET_ACTIVE_CMDID);
  402. if (QDF_IS_STATUS_ERROR(status)) {
  403. wmi_err("Failed to send MLO link set active command to FW: %d",
  404. status);
  405. wmi_buf_free(buf);
  406. }
  407. return status;
  408. }
  409. /**
  410. * extract_mlo_link_set_active_resp_tlv() - extract mlo link set active resp
  411. * from event
  412. * @wmi_handle: wmi handle
  413. * @evt_buf: pointer to event buffer
  414. * @resp: Pointer to hold mlo link set active resp
  415. *
  416. * Return: QDF_STATUS_SUCCESS for success or QDF_STATUS_E_* for error
  417. */
  418. static QDF_STATUS
  419. extract_mlo_link_set_active_resp_tlv(wmi_unified_t wmi_handle, void *evt_buf,
  420. struct mlo_link_set_active_resp *resp)
  421. {
  422. wmi_mlo_link_set_active_resp_event_fixed_param *evt;
  423. WMI_MLO_LINK_SET_ACTIVE_RESP_EVENTID_param_tlvs *param_buf;
  424. uint32_t entry_num, *bitmap;
  425. int i;
  426. param_buf = evt_buf;
  427. if (!param_buf || !resp) {
  428. wmi_err("Invalid param");
  429. return QDF_STATUS_E_INVAL;
  430. }
  431. evt = param_buf->fixed_param;
  432. resp->status = evt->status;
  433. wmi_debug("status: %u", resp->status);
  434. bitmap = param_buf->force_active_vdev_bitmap;
  435. entry_num = qdf_min(param_buf->num_force_active_vdev_bitmap,
  436. (uint32_t)MLO_VDEV_BITMAP_SZ);
  437. resp->active_sz = entry_num;
  438. for (i = 0; i < entry_num; i++) {
  439. resp->active[i] = bitmap[i];
  440. wmi_debug("active[%d]: 0x%x", i, resp->active[i]);
  441. }
  442. bitmap = param_buf->force_inactive_vdev_bitmap;
  443. entry_num = qdf_min(param_buf->num_force_inactive_vdev_bitmap,
  444. (uint32_t)MLO_VDEV_BITMAP_SZ);
  445. resp->inactive_sz = entry_num;
  446. for (i = 0; i < entry_num; i++) {
  447. resp->inactive[i] = bitmap[i];
  448. wmi_debug("inactive[%d]: 0x%x", i, resp->inactive[i]);
  449. }
  450. return QDF_STATUS_SUCCESS;
  451. }
  452. #ifdef WLAN_MLO_MULTI_CHIP
  453. QDF_STATUS mlo_setup_cmd_send_tlv(struct wmi_unified *wmi_handle,
  454. struct wmi_mlo_setup_params *param)
  455. {
  456. QDF_STATUS ret;
  457. wmi_mlo_setup_cmd_fixed_param *cmd;
  458. wmi_buf_t buf;
  459. int32_t len;
  460. uint8_t *buf_ptr;
  461. uint32_t *partner_links;
  462. uint8_t idx;
  463. if (param->num_valid_hw_links > MAX_LINK_IN_MLO)
  464. return QDF_STATUS_E_INVAL;
  465. len = sizeof(*cmd) +
  466. (param->num_valid_hw_links * sizeof(uint32_t)) +
  467. WMI_TLV_HDR_SIZE;
  468. buf = wmi_buf_alloc(wmi_handle, len);
  469. if (!buf)
  470. return QDF_STATUS_E_NOMEM;
  471. cmd = (wmi_mlo_setup_cmd_fixed_param *)wmi_buf_data(buf);
  472. WMITLV_SET_HDR(&cmd->tlv_header,
  473. WMITLV_TAG_STRUC_wmi_mlo_setup_cmd_fixed_param,
  474. WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_setup_cmd_fixed_param));
  475. cmd->mld_group_id = param->mld_grp_id;
  476. cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
  477. wmi_handle,
  478. param->pdev_id);
  479. buf_ptr = (uint8_t *)cmd + sizeof(*cmd);
  480. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
  481. (sizeof(uint32_t) * param->num_valid_hw_links));
  482. partner_links = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE);
  483. for (idx = 0; idx < param->num_valid_hw_links; idx++)
  484. partner_links[idx] = param->partner_links[idx];
  485. wmi_mtrace(WMI_MLO_SETUP_CMDID, NO_SESSION, 0);
  486. ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_MLO_SETUP_CMDID);
  487. if (QDF_IS_STATUS_ERROR(ret)) {
  488. wmi_err("Failed to send MLO setup command ret = %d", ret);
  489. wmi_buf_free(buf);
  490. }
  491. return ret;
  492. }
  493. QDF_STATUS mlo_ready_cmd_send_tlv(struct wmi_unified *wmi_handle,
  494. struct wmi_mlo_ready_params *param)
  495. {
  496. QDF_STATUS ret;
  497. wmi_mlo_ready_cmd_fixed_param *cmd;
  498. wmi_buf_t buf;
  499. int32_t len;
  500. len = sizeof(*cmd);
  501. buf = wmi_buf_alloc(wmi_handle, len);
  502. if (!buf)
  503. return QDF_STATUS_E_NOMEM;
  504. cmd = (wmi_mlo_ready_cmd_fixed_param *)wmi_buf_data(buf);
  505. WMITLV_SET_HDR(&cmd->tlv_header,
  506. WMITLV_TAG_STRUC_wmi_mlo_ready_cmd_fixed_param,
  507. WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_ready_cmd_fixed_param));
  508. cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
  509. wmi_handle,
  510. param->pdev_id);
  511. wmi_mtrace(WMI_MLO_READY_CMDID, NO_SESSION, 0);
  512. ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_MLO_READY_CMDID);
  513. if (QDF_IS_STATUS_ERROR(ret)) {
  514. wmi_err("Failed to send MLO ready command ret = %d", ret);
  515. wmi_buf_free(buf);
  516. }
  517. return ret;
  518. }
  519. QDF_STATUS mlo_teardown_cmd_send_tlv(struct wmi_unified *wmi_handle,
  520. struct wmi_mlo_teardown_params *param)
  521. {
  522. QDF_STATUS ret;
  523. wmi_mlo_teardown_fixed_param *cmd;
  524. wmi_buf_t buf;
  525. int32_t len;
  526. len = sizeof(*cmd);
  527. buf = wmi_buf_alloc(wmi_handle, len);
  528. if (!buf)
  529. return QDF_STATUS_E_NOMEM;
  530. cmd = (wmi_mlo_teardown_fixed_param *)wmi_buf_data(buf);
  531. WMITLV_SET_HDR(&cmd->tlv_header,
  532. WMITLV_TAG_STRUC_wmi_mlo_teardown_fixed_param,
  533. WMITLV_GET_STRUCT_TLVLEN(wmi_mlo_teardown_fixed_param));
  534. cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
  535. wmi_handle,
  536. param->pdev_id);
  537. switch (param->reason) {
  538. case WMI_MLO_TEARDOWN_REASON_SSR:
  539. cmd->reason_code = WMI_MLO_TEARDOWN_SSR_REASON;
  540. break;
  541. case WMI_MLO_TEARDOWN_REASON_DOWN:
  542. default:
  543. cmd->reason_code = WMI_MLO_TEARDOWN_SSR_REASON + 1;
  544. break;
  545. }
  546. wmi_mtrace(WMI_MLO_TEARDOWN_CMDID, NO_SESSION, 0);
  547. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  548. WMI_MLO_TEARDOWN_CMDID);
  549. if (QDF_IS_STATUS_ERROR(ret)) {
  550. wmi_err("Failed to send MLO Teardown command ret = %d", ret);
  551. wmi_buf_free(buf);
  552. }
  553. return ret;
  554. }
  555. QDF_STATUS
  556. extract_mlo_setup_cmpl_event_tlv(struct wmi_unified *wmi_handle,
  557. uint8_t *buf,
  558. struct wmi_mlo_setup_complete_params *params)
  559. {
  560. WMI_MLO_SETUP_COMPLETE_EVENTID_param_tlvs *param_buf;
  561. wmi_mlo_setup_complete_event_fixed_param *ev;
  562. param_buf = (WMI_MLO_SETUP_COMPLETE_EVENTID_param_tlvs *)buf;
  563. if (!param_buf) {
  564. wmi_err_rl("Param_buf is NULL");
  565. return QDF_STATUS_E_FAILURE;
  566. }
  567. ev = (wmi_mlo_setup_complete_event_fixed_param *)param_buf->fixed_param;
  568. params->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host(
  569. wmi_handle,
  570. ev->pdev_id);
  571. if (!ev->status)
  572. params->status = WMI_MLO_SETUP_STATUS_SUCCESS;
  573. else
  574. params->status = WMI_MLO_SETUP_STATUS_FAILURE;
  575. return QDF_STATUS_SUCCESS;
  576. }
  577. QDF_STATUS
  578. extract_mlo_teardown_cmpl_event_tlv(struct wmi_unified *wmi_handle,
  579. uint8_t *buf,
  580. struct wmi_mlo_teardown_cmpl_params *params)
  581. {
  582. WMI_MLO_TEARDOWN_COMPLETE_EVENTID_param_tlvs *param_buf;
  583. wmi_mlo_teardown_complete_fixed_param *ev;
  584. param_buf = (WMI_MLO_TEARDOWN_COMPLETE_EVENTID_param_tlvs *)buf;
  585. if (!param_buf) {
  586. wmi_err_rl("Param_buf is NULL");
  587. return QDF_STATUS_E_FAILURE;
  588. }
  589. ev = (wmi_mlo_teardown_complete_fixed_param *)param_buf->fixed_param;
  590. params->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host(
  591. wmi_handle,
  592. ev->pdev_id);
  593. if (!ev->status)
  594. params->status = WMI_MLO_TEARDOWN_STATUS_SUCCESS;
  595. else
  596. params->status = WMI_MLO_TEARDOWN_STATUS_FAILURE;
  597. return QDF_STATUS_SUCCESS;
  598. }
  599. static void wmi_11be_attach_mlo_setup_tlv(wmi_unified_t wmi_handle)
  600. {
  601. struct wmi_ops *ops = wmi_handle->ops;
  602. ops->mlo_setup_cmd_send = mlo_setup_cmd_send_tlv;
  603. ops->mlo_teardown_cmd_send = mlo_teardown_cmd_send_tlv;
  604. ops->mlo_ready_cmd_send = mlo_ready_cmd_send_tlv;
  605. ops->extract_mlo_setup_cmpl_event = extract_mlo_setup_cmpl_event_tlv;
  606. ops->extract_mlo_teardown_cmpl_event =
  607. extract_mlo_teardown_cmpl_event_tlv;
  608. }
  609. #else /*WLAN_MLO_MULTI_CHIP*/
  610. static void wmi_11be_attach_mlo_setup_tlv(wmi_unified_t wmi_handle)
  611. {}
  612. #endif /*WLAN_MLO_MULTI_CHIP*/
  613. void wmi_11be_attach_tlv(wmi_unified_t wmi_handle)
  614. {
  615. struct wmi_ops *ops = wmi_handle->ops;
  616. wmi_11be_attach_mlo_setup_tlv(wmi_handle);
  617. ops->extract_mlo_link_set_active_resp =
  618. extract_mlo_link_set_active_resp_tlv;
  619. ops->send_mlo_link_set_active_cmd =
  620. send_mlo_link_set_active_cmd_tlv;
  621. }