wmi_unified_vdev_tlv.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /*
  2. * Copyright (c) 2016-2020 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. #include <osdep.h>
  19. #include <qdf_module.h>
  20. #include <qdf_list.h>
  21. #include <qdf_platform.h>
  22. #include <wmi_unified_vdev_tlv.h>
  23. #include <wlan_vdev_mgr_tgt_if_tx_defs.h>
  24. static QDF_STATUS
  25. send_vdev_config_ratemask_cmd_tlv(struct wmi_unified *wmi_handle,
  26. struct config_ratemask_params *param)
  27. {
  28. wmi_vdev_config_ratemask_cmd_fixed_param *cmd;
  29. wmi_buf_t buf;
  30. int32_t len = sizeof(*cmd);
  31. buf = wmi_buf_alloc(wmi_handle, len);
  32. if (!buf) {
  33. WMI_LOGE("%s:wmi_buf_alloc failed", __func__);
  34. return QDF_STATUS_E_FAILURE;
  35. }
  36. cmd = (wmi_vdev_config_ratemask_cmd_fixed_param *)wmi_buf_data(buf);
  37. WMITLV_SET_HDR(&cmd->tlv_header,
  38. WMITLV_TAG_STRUC_wmi_vdev_config_ratemask_fixed_param,
  39. WMITLV_GET_STRUCT_TLVLEN(
  40. wmi_vdev_config_ratemask_cmd_fixed_param));
  41. cmd->vdev_id = param->vdev_id;
  42. cmd->type = param->type;
  43. cmd->mask_lower32 = param->lower32;
  44. cmd->mask_higher32 = param->higher32;
  45. cmd->mask_lower32_2 = param->lower32_2;
  46. cmd->mask_higher32_2 = param->higher32_2;
  47. wmi_mtrace(WMI_VDEV_RATEMASK_CMDID, cmd->vdev_id, 0);
  48. if (wmi_unified_cmd_send(wmi_handle, buf, len,
  49. WMI_VDEV_RATEMASK_CMDID)) {
  50. WMI_LOGE("Seting vdev ratemask failed");
  51. wmi_buf_free(buf);
  52. return QDF_STATUS_E_FAILURE;
  53. }
  54. return QDF_STATUS_SUCCESS;
  55. }
  56. static QDF_STATUS
  57. send_beacon_send_cmd_tlv(struct wmi_unified *wmi_handle,
  58. struct beacon_params *param)
  59. {
  60. QDF_STATUS ret;
  61. wmi_bcn_send_from_host_cmd_fixed_param *cmd;
  62. wmi_buf_t wmi_buf;
  63. qdf_dma_addr_t dma_addr;
  64. uint32_t dtim_flag = 0;
  65. wmi_buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
  66. if (!wmi_buf) {
  67. WMI_LOGE("%s : wmi_buf_alloc failed", __func__);
  68. return QDF_STATUS_E_NOMEM;
  69. }
  70. if (param->is_dtim_count_zero) {
  71. dtim_flag |= WMI_BCN_SEND_DTIM_ZERO;
  72. if (param->is_bitctl_reqd) {
  73. /* deliver CAB traffic in next DTIM beacon */
  74. dtim_flag |= WMI_BCN_SEND_DTIM_BITCTL_SET;
  75. }
  76. }
  77. cmd = (wmi_bcn_send_from_host_cmd_fixed_param *)wmi_buf_data(wmi_buf);
  78. WMITLV_SET_HDR(
  79. &cmd->tlv_header,
  80. WMITLV_TAG_STRUC_wmi_bcn_send_from_host_cmd_fixed_param,
  81. WMITLV_GET_STRUCT_TLVLEN
  82. (wmi_bcn_send_from_host_cmd_fixed_param));
  83. cmd->vdev_id = param->vdev_id;
  84. cmd->data_len = qdf_nbuf_len(param->wbuf);
  85. cmd->frame_ctrl = param->frame_ctrl;
  86. cmd->dtim_flag = dtim_flag;
  87. dma_addr = qdf_nbuf_get_frag_paddr(param->wbuf, 0);
  88. cmd->frag_ptr_lo = qdf_get_lower_32_bits(dma_addr);
  89. #if defined(HTT_PADDR64)
  90. cmd->frag_ptr_hi = qdf_get_upper_32_bits(dma_addr) & 0x1F;
  91. #endif
  92. cmd->bcn_antenna = param->bcn_txant;
  93. wmi_mtrace(WMI_PDEV_SEND_BCN_CMDID, cmd->vdev_id, 0);
  94. ret = wmi_unified_cmd_send(wmi_handle, wmi_buf, sizeof(*cmd),
  95. WMI_PDEV_SEND_BCN_CMDID);
  96. if (ret != QDF_STATUS_SUCCESS) {
  97. WMI_LOGE("%s: Failed to send bcn: %d", __func__, ret);
  98. wmi_buf_free(wmi_buf);
  99. }
  100. return ret;
  101. }
  102. static QDF_STATUS
  103. extract_tbttoffset_num_vdevs_tlv(struct wmi_unified *wmi_handle, void *evt_buf,
  104. uint32_t *num_vdevs)
  105. {
  106. WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf;
  107. wmi_tbtt_offset_event_fixed_param *tbtt_offset_event;
  108. uint32_t vdev_map;
  109. param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *)evt_buf;
  110. if (!param_buf) {
  111. WMI_LOGE("%s: Invalid tbtt update ext event buffer", __func__);
  112. return QDF_STATUS_E_INVAL;
  113. }
  114. tbtt_offset_event = param_buf->fixed_param;
  115. vdev_map = tbtt_offset_event->vdev_map;
  116. *num_vdevs = wmi_vdev_map_to_num_vdevs(vdev_map);
  117. return QDF_STATUS_SUCCESS;
  118. }
  119. static QDF_STATUS
  120. send_vdev_set_neighbour_rx_cmd_tlv(struct wmi_unified *wmi_handle,
  121. uint8_t macaddr[QDF_MAC_ADDR_SIZE],
  122. struct set_neighbour_rx_params *param)
  123. {
  124. wmi_vdev_filter_nrp_config_cmd_fixed_param *cmd;
  125. wmi_buf_t buf;
  126. int32_t len = sizeof(*cmd);
  127. buf = wmi_buf_alloc(wmi_handle, len);
  128. if (!buf) {
  129. WMI_LOGE("%s:wmi_buf_alloc failed", __func__);
  130. return QDF_STATUS_E_FAILURE;
  131. }
  132. cmd = (wmi_vdev_filter_nrp_config_cmd_fixed_param *)wmi_buf_data(buf);
  133. WMITLV_SET_HDR(&cmd->tlv_header,
  134. WMITLV_TAG_STRUC_wmi_vdev_filter_nrp_config_cmd_fixed_param,
  135. WMITLV_GET_STRUCT_TLVLEN(
  136. wmi_vdev_filter_nrp_config_cmd_fixed_param));
  137. cmd->vdev_id = param->vdev_id;
  138. cmd->bssid_idx = param->idx;
  139. cmd->action = param->action;
  140. cmd->type = param->type;
  141. WMI_CHAR_ARRAY_TO_MAC_ADDR(macaddr, &cmd->addr);
  142. cmd->flag = 0;
  143. wmi_mtrace(WMI_VDEV_FILTER_NEIGHBOR_RX_PACKETS_CMDID, cmd->vdev_id, 0);
  144. if (wmi_unified_cmd_send(wmi_handle, buf, len,
  145. WMI_VDEV_FILTER_NEIGHBOR_RX_PACKETS_CMDID)) {
  146. WMI_LOGE("Failed to set neighbour rx param");
  147. wmi_buf_free(buf);
  148. return QDF_STATUS_E_FAILURE;
  149. }
  150. return QDF_STATUS_SUCCESS;
  151. }
  152. static QDF_STATUS
  153. extract_vdev_start_resp_tlv(struct wmi_unified *wmi_handle, void *evt_buf,
  154. struct vdev_start_response *vdev_rsp)
  155. {
  156. WMI_VDEV_START_RESP_EVENTID_param_tlvs *param_buf;
  157. wmi_vdev_start_response_event_fixed_param *ev;
  158. param_buf = (WMI_VDEV_START_RESP_EVENTID_param_tlvs *)evt_buf;
  159. if (!param_buf) {
  160. WMI_LOGE("%s: Invalid start response event buffer", __func__);
  161. return QDF_STATUS_E_INVAL;
  162. }
  163. ev = param_buf->fixed_param;
  164. if (!ev) {
  165. WMI_LOGE("%s: Invalid start response event buffer", __func__);
  166. return QDF_STATUS_E_INVAL;
  167. }
  168. qdf_mem_zero(vdev_rsp, sizeof(*vdev_rsp));
  169. vdev_rsp->vdev_id = ev->vdev_id;
  170. vdev_rsp->requestor_id = ev->requestor_id;
  171. switch (ev->resp_type) {
  172. case WMI_VDEV_START_RESP_EVENT:
  173. vdev_rsp->resp_type = WMI_HOST_VDEV_START_RESP_EVENT;
  174. break;
  175. case WMI_VDEV_RESTART_RESP_EVENT:
  176. vdev_rsp->resp_type = WMI_HOST_VDEV_RESTART_RESP_EVENT;
  177. break;
  178. default:
  179. WMI_LOGE("Invalid start response event buffer");
  180. break;
  181. };
  182. vdev_rsp->status = ev->status;
  183. vdev_rsp->chain_mask = ev->chain_mask;
  184. vdev_rsp->smps_mode = ev->smps_mode;
  185. vdev_rsp->mac_id = ev->mac_id;
  186. vdev_rsp->cfgd_tx_streams = ev->cfgd_tx_streams;
  187. vdev_rsp->cfgd_rx_streams = ev->cfgd_rx_streams;
  188. vdev_rsp->max_allowed_tx_power = ev->max_allowed_tx_power;
  189. return QDF_STATUS_SUCCESS;
  190. }
  191. static QDF_STATUS
  192. extract_vdev_delete_resp_tlv(struct wmi_unified *wmi_handle, void *evt_buf,
  193. struct vdev_delete_response *delete_rsp)
  194. {
  195. WMI_VDEV_DELETE_RESP_EVENTID_param_tlvs *param_buf;
  196. wmi_vdev_delete_resp_event_fixed_param *ev;
  197. param_buf = (WMI_VDEV_DELETE_RESP_EVENTID_param_tlvs *)evt_buf;
  198. if (!param_buf) {
  199. WMI_LOGE("Invalid vdev delete response event buffer");
  200. return QDF_STATUS_E_INVAL;
  201. }
  202. ev = param_buf->fixed_param;
  203. if (!ev) {
  204. WMI_LOGE("Invalid vdev delete response event");
  205. return QDF_STATUS_E_INVAL;
  206. }
  207. qdf_mem_zero(delete_rsp, sizeof(*delete_rsp));
  208. delete_rsp->vdev_id = ev->vdev_id;
  209. return QDF_STATUS_SUCCESS;
  210. }
  211. static QDF_STATUS extract_vdev_peer_delete_all_response_event_tlv(
  212. wmi_unified_t wmi_hdl,
  213. void *evt_buf,
  214. struct peer_delete_all_response *param)
  215. {
  216. WMI_VDEV_DELETE_ALL_PEER_RESP_EVENTID_param_tlvs *param_buf;
  217. wmi_vdev_delete_all_peer_resp_event_fixed_param *ev;
  218. param_buf = (WMI_VDEV_DELETE_ALL_PEER_RESP_EVENTID_param_tlvs *)evt_buf;
  219. ev = (wmi_vdev_delete_all_peer_resp_event_fixed_param *)
  220. param_buf->fixed_param;
  221. if (!ev) {
  222. WMI_LOGE("%s: Invalid peer_delete all response", __func__);
  223. return QDF_STATUS_E_FAILURE;
  224. }
  225. param->vdev_id = ev->vdev_id;
  226. param->status = ev->status;
  227. return QDF_STATUS_SUCCESS;
  228. }
  229. static QDF_STATUS
  230. extract_vdev_stopped_param_tlv(struct wmi_unified *wmi_handle,
  231. void *evt_buf, uint32_t *vdev_id)
  232. {
  233. WMI_VDEV_STOPPED_EVENTID_param_tlvs *param_buf;
  234. wmi_vdev_stopped_event_fixed_param *resp_event;
  235. param_buf = (WMI_VDEV_STOPPED_EVENTID_param_tlvs *)evt_buf;
  236. if (!param_buf) {
  237. WMI_LOGE("Invalid event buffer");
  238. return QDF_STATUS_E_INVAL;
  239. }
  240. resp_event = param_buf->fixed_param;
  241. *vdev_id = resp_event->vdev_id;
  242. return QDF_STATUS_SUCCESS;
  243. }
  244. static QDF_STATUS extract_ext_tbttoffset_num_vdevs_tlv(
  245. wmi_unified_t wmi_hdl,
  246. void *evt_buf,
  247. uint32_t *num_vdevs)
  248. {
  249. WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *param_buf;
  250. wmi_tbtt_offset_ext_event_fixed_param *tbtt_offset_ext_event;
  251. param_buf = (WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *)evt_buf;
  252. if (!param_buf) {
  253. WMI_LOGE("%s Invalid tbtt update ext event buffer", __func__);
  254. return QDF_STATUS_E_INVAL;
  255. }
  256. tbtt_offset_ext_event = param_buf->fixed_param;
  257. *num_vdevs = tbtt_offset_ext_event->num_vdevs;
  258. return QDF_STATUS_SUCCESS;
  259. }
  260. static QDF_STATUS extract_tbttoffset_update_params_tlv(
  261. wmi_unified_t wmi_hdl,
  262. void *evt_buf, uint8_t idx,
  263. struct tbttoffset_params *tbtt_param)
  264. {
  265. WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf;
  266. wmi_tbtt_offset_event_fixed_param *tbtt_offset_event;
  267. uint32_t vdev_map;
  268. param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *)evt_buf;
  269. if (!param_buf) {
  270. WMI_LOGE("%s: Invalid tbtt update event buffer", __func__);
  271. return QDF_STATUS_E_INVAL;
  272. }
  273. tbtt_offset_event = param_buf->fixed_param;
  274. vdev_map = tbtt_offset_event->vdev_map;
  275. tbtt_param->vdev_id = wmi_vdev_map_to_vdev_id(vdev_map, idx);
  276. if (tbtt_param->vdev_id == WLAN_INVALID_VDEV_ID)
  277. return QDF_STATUS_E_INVAL;
  278. tbtt_param->tbttoffset =
  279. param_buf->tbttoffset_list[tbtt_param->vdev_id];
  280. if (param_buf->tbtt_qtime_low_us_list)
  281. tbtt_param->vdev_tbtt_qtime_lo =
  282. param_buf->tbtt_qtime_low_us_list[tbtt_param->vdev_id];
  283. if (param_buf->tbtt_qtime_high_us_list)
  284. tbtt_param->vdev_tbtt_qtime_hi =
  285. param_buf->tbtt_qtime_high_us_list[tbtt_param->vdev_id];
  286. return QDF_STATUS_SUCCESS;
  287. }
  288. static QDF_STATUS extract_ext_tbttoffset_update_params_tlv(
  289. wmi_unified_t wmi_hdl,
  290. void *evt_buf, uint8_t idx,
  291. struct tbttoffset_params *tbtt_param)
  292. {
  293. WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *param_buf;
  294. wmi_tbtt_offset_info *tbtt_offset_info;
  295. param_buf = (WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *)evt_buf;
  296. if (!param_buf) {
  297. WMI_LOGE("%s: Invalid tbtt update event buffer", __func__);
  298. return QDF_STATUS_E_INVAL;
  299. }
  300. tbtt_offset_info = &param_buf->tbtt_offset_info[idx];
  301. tbtt_param->vdev_id = tbtt_offset_info->vdev_id;
  302. tbtt_param->tbttoffset = tbtt_offset_info->tbttoffset;
  303. tbtt_param->vdev_tbtt_qtime_lo = tbtt_offset_info->tbtt_qtime_low_us;
  304. tbtt_param->vdev_tbtt_qtime_hi = tbtt_offset_info->tbtt_qtime_high_us;
  305. return QDF_STATUS_SUCCESS;
  306. }
  307. static QDF_STATUS extract_muedca_params_tlv(wmi_unified_t wmi_hdl,
  308. void *evt_buf,
  309. struct muedca_params *muedca_param_list)
  310. {
  311. WMI_MUEDCA_PARAMS_CONFIG_EVENTID_param_tlvs *param_buf;
  312. wmi_muedca_params_config_event_fixed_param *muedca_param;
  313. int i;
  314. param_buf = (WMI_MUEDCA_PARAMS_CONFIG_EVENTID_param_tlvs *)evt_buf;
  315. if (!param_buf) {
  316. WMI_LOGE("%s: Invalid muedca evt buffer", __func__);
  317. return QDF_STATUS_E_INVAL;
  318. }
  319. muedca_param = param_buf->fixed_param;
  320. muedca_param_list->pdev_id = wmi_hdl->ops->
  321. convert_target_pdev_id_to_host(wmi_hdl,
  322. muedca_param->pdev_id);
  323. for (i = 0; i < WMI_AC_MAX; i++) {
  324. muedca_param_list->muedca_aifsn[i] = muedca_param->aifsn[i] &
  325. WMI_MUEDCA_PARAM_MASK;
  326. muedca_param_list->muedca_ecwmin[i] = muedca_param->ecwmin[i] &
  327. WMI_MUEDCA_PARAM_MASK;
  328. muedca_param_list->muedca_ecwmax[i] = muedca_param->ecwmax[i] &
  329. WMI_MUEDCA_PARAM_MASK;
  330. muedca_param_list->muedca_timer[i] = muedca_param->muedca_expiration_time[i] &
  331. WMI_MUEDCA_PARAM_MASK;
  332. }
  333. return QDF_STATUS_SUCCESS;
  334. }
  335. void wmi_vdev_attach_tlv(struct wmi_unified *wmi_handle)
  336. {
  337. struct wmi_ops *wmi_ops;
  338. if (!wmi_handle) {
  339. wmi_err("null wmi handle");
  340. return;
  341. }
  342. wmi_ops = wmi_handle->ops;
  343. wmi_ops->extract_vdev_delete_resp = extract_vdev_delete_resp_tlv;
  344. wmi_ops->extract_vdev_stopped_param = extract_vdev_stopped_param_tlv;
  345. wmi_ops->extract_vdev_start_resp = extract_vdev_start_resp_tlv;
  346. wmi_ops->extract_vdev_peer_delete_all_response_event =
  347. extract_vdev_peer_delete_all_response_event_tlv;
  348. wmi_ops->extract_tbttoffset_num_vdevs =
  349. extract_tbttoffset_num_vdevs_tlv;
  350. wmi_ops->extract_tbttoffset_update_params =
  351. extract_tbttoffset_update_params_tlv;
  352. wmi_ops->extract_ext_tbttoffset_update_params =
  353. extract_ext_tbttoffset_update_params_tlv;
  354. wmi_ops->extract_ext_tbttoffset_num_vdevs =
  355. extract_ext_tbttoffset_num_vdevs_tlv;
  356. wmi_ops->extract_muedca_params_handler =
  357. extract_muedca_params_tlv;
  358. wmi_ops->send_vdev_set_neighbour_rx_cmd =
  359. send_vdev_set_neighbour_rx_cmd_tlv;
  360. wmi_ops->send_beacon_send_cmd = send_beacon_send_cmd_tlv;
  361. wmi_ops->send_vdev_config_ratemask_cmd =
  362. send_vdev_config_ratemask_cmd_tlv;
  363. }