wmi_unified_smart_ant_tlv.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /*
  2. * Copyright (c) 2016-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. #include <osdep.h>
  19. #include "wmi.h"
  20. #include "wmi_unified_priv.h"
  21. #include "wmi_unified_smart_ant_param.h"
  22. #include "wmi_unified_smart_ant_api.h"
  23. #ifdef WMI_SMART_ANT_SUPPORT
  24. /**
  25. * send_smart_ant_enable_cmd_tlv() - WMI smart ant enable function
  26. *
  27. * @param wmi_handle : handle to WMI.
  28. * @param param : pointer to antenna param
  29. *
  30. * This function sends smart antenna enable command to FW
  31. *
  32. * @return QDF_STATUS_SUCCESS on success and -ve on failure.
  33. */
  34. static QDF_STATUS send_smart_ant_enable_cmd_tlv(wmi_unified_t wmi_handle,
  35. struct smart_ant_enable_params *param)
  36. {
  37. /* Send WMI COMMAND to Enable */
  38. wmi_pdev_smart_ant_enable_cmd_fixed_param *cmd;
  39. wmi_pdev_smart_ant_gpio_handle *gpio_param;
  40. wmi_buf_t buf;
  41. uint8_t *buf_ptr;
  42. int len = 0;
  43. QDF_STATUS ret;
  44. int loop = 0;
  45. len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
  46. len += WMI_HAL_MAX_SANTENNA * sizeof(wmi_pdev_smart_ant_gpio_handle);
  47. buf = wmi_buf_alloc(wmi_handle, len);
  48. if (!buf) {
  49. WMI_LOGE("%s:wmi_buf_alloc failed\n", __func__);
  50. return QDF_STATUS_E_NOMEM;
  51. }
  52. buf_ptr = wmi_buf_data(buf);
  53. qdf_mem_zero(buf_ptr, len);
  54. cmd = (wmi_pdev_smart_ant_enable_cmd_fixed_param *)buf_ptr;
  55. WMITLV_SET_HDR(&cmd->tlv_header,
  56. WMITLV_TAG_STRUC_wmi_pdev_smart_ant_enable_cmd_fixed_param,
  57. WMITLV_GET_STRUCT_TLVLEN(
  58. wmi_pdev_smart_ant_enable_cmd_fixed_param));
  59. cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
  60. wmi_handle,
  61. param->pdev_id);
  62. cmd->enable = param->enable;
  63. cmd->mode = param->mode;
  64. cmd->rx_antenna = param->rx_antenna;
  65. cmd->tx_default_antenna = param->rx_antenna;
  66. /* TLV indicating array of structures to follow */
  67. buf_ptr += sizeof(wmi_pdev_smart_ant_enable_cmd_fixed_param);
  68. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  69. WMI_HAL_MAX_SANTENNA *
  70. sizeof(wmi_pdev_smart_ant_gpio_handle));
  71. buf_ptr += WMI_TLV_HDR_SIZE;
  72. gpio_param = (wmi_pdev_smart_ant_gpio_handle *)buf_ptr;
  73. for (loop = 0; loop < WMI_HAL_MAX_SANTENNA; loop++) {
  74. WMITLV_SET_HDR(&gpio_param->tlv_header,
  75. WMITLV_TAG_STRUC_wmi_pdev_smart_ant_gpio_handle,
  76. WMITLV_GET_STRUCT_TLVLEN(
  77. wmi_pdev_smart_ant_gpio_handle));
  78. if (param->mode == SMART_ANT_MODE_SERIAL) {
  79. if (loop < WMI_HOST_MAX_SERIAL_ANTENNA) {
  80. gpio_param->gpio_pin = param->gpio_pin[loop];
  81. gpio_param->gpio_func = param->gpio_func[loop];
  82. } else {
  83. gpio_param->gpio_pin = 0;
  84. gpio_param->gpio_func = 0;
  85. }
  86. } else if (param->mode == SMART_ANT_MODE_PARALLEL) {
  87. gpio_param->gpio_pin = param->gpio_pin[loop];
  88. gpio_param->gpio_func = param->gpio_func[loop];
  89. }
  90. /* Setting it to 0 for now */
  91. gpio_param->pdev_id =
  92. wmi_handle->ops->convert_pdev_id_host_to_target(
  93. wmi_handle,
  94. param->pdev_id);
  95. gpio_param++;
  96. }
  97. wmi_mtrace(WMI_PDEV_SMART_ANT_ENABLE_CMDID, NO_SESSION, 0);
  98. ret = wmi_unified_cmd_send(wmi_handle,
  99. buf,
  100. len,
  101. WMI_PDEV_SMART_ANT_ENABLE_CMDID);
  102. if (ret != 0) {
  103. WMI_LOGE(" %s :WMI Failed\n", __func__);
  104. WMI_LOGE("enable:%d mode:%d rx_antenna: 0x%08x PINS: [%d %d %d %d] Func[%d %d %d %d] cmdstatus=%d\n",
  105. cmd->enable,
  106. cmd->mode,
  107. cmd->rx_antenna,
  108. param->gpio_pin[0], param->gpio_pin[1],
  109. param->gpio_pin[2], param->gpio_pin[3],
  110. param->gpio_func[0], param->gpio_func[1],
  111. param->gpio_func[2], param->gpio_func[3],
  112. ret);
  113. wmi_buf_free(buf);
  114. }
  115. return ret;
  116. }
  117. /**
  118. * send_smart_ant_set_rx_ant_cmd_tlv() - WMI set rx antenna function
  119. *
  120. * @param wmi_handle : handle to WMI.
  121. * @param param : pointer to rx antenna param
  122. * @return QDF_STATUS_SUCCESS on success and -ve on failure.
  123. */
  124. static QDF_STATUS send_smart_ant_set_rx_ant_cmd_tlv(wmi_unified_t wmi_handle,
  125. struct smart_ant_rx_ant_params *param)
  126. {
  127. wmi_pdev_smart_ant_set_rx_antenna_cmd_fixed_param *cmd;
  128. wmi_buf_t buf;
  129. uint8_t *buf_ptr;
  130. uint32_t len;
  131. QDF_STATUS ret;
  132. len = sizeof(*cmd);
  133. buf = wmi_buf_alloc(wmi_handle, len);
  134. WMI_LOGD("%s:\n", __func__);
  135. if (!buf) {
  136. WMI_LOGE("%s:wmi_buf_alloc failed\n", __func__);
  137. return QDF_STATUS_E_NOMEM;
  138. }
  139. buf_ptr = wmi_buf_data(buf);
  140. cmd = (wmi_pdev_smart_ant_set_rx_antenna_cmd_fixed_param *)buf_ptr;
  141. WMITLV_SET_HDR(&cmd->tlv_header,
  142. WMITLV_TAG_STRUC_wmi_pdev_smart_ant_set_rx_antenna_cmd_fixed_param,
  143. WMITLV_GET_STRUCT_TLVLEN(
  144. wmi_pdev_smart_ant_set_rx_antenna_cmd_fixed_param));
  145. cmd->rx_antenna = param->antenna;
  146. cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
  147. wmi_handle,
  148. param->pdev_id);
  149. wmi_mtrace(WMI_PDEV_SMART_ANT_SET_RX_ANTENNA_CMDID, NO_SESSION, 0);
  150. ret = wmi_unified_cmd_send(wmi_handle,
  151. buf,
  152. len,
  153. WMI_PDEV_SMART_ANT_SET_RX_ANTENNA_CMDID);
  154. if (ret != 0) {
  155. WMI_LOGE(" %s :WMI Failed\n", __func__);
  156. WMI_LOGE("%s: rx_antenna: 0x%08x cmdstatus=%d\n",
  157. __func__,
  158. cmd->rx_antenna,
  159. ret);
  160. wmi_buf_free(buf);
  161. }
  162. return ret;
  163. }
  164. /**
  165. * send_smart_ant_set_tx_ant_cmd_tlv() - WMI set tx antenna function
  166. * @param wmi_handle : handle to WMI.
  167. * @param macaddr : vdev mac address
  168. * @param param : pointer to tx antenna param
  169. *
  170. * @return QDF_STATUS_SUCCESS on success and -ve on failure.
  171. */
  172. static QDF_STATUS send_smart_ant_set_tx_ant_cmd_tlv(wmi_unified_t wmi_handle,
  173. uint8_t macaddr[QDF_MAC_ADDR_SIZE],
  174. struct smart_ant_tx_ant_params *param)
  175. {
  176. wmi_peer_smart_ant_set_tx_antenna_cmd_fixed_param *cmd;
  177. wmi_peer_smart_ant_set_tx_antenna_series *ant_tx_series;
  178. wmi_buf_t buf;
  179. int32_t len = 0;
  180. int i;
  181. uint8_t *buf_ptr;
  182. QDF_STATUS ret;
  183. len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
  184. len += (WMI_SMART_ANT_MAX_RATE_SERIES) *
  185. sizeof(wmi_peer_smart_ant_set_tx_antenna_series);
  186. buf = wmi_buf_alloc(wmi_handle, len);
  187. if (!buf) {
  188. WMI_LOGE("%s:wmi_buf_alloc failed\n", __func__);
  189. return QDF_STATUS_E_NOMEM;
  190. }
  191. buf_ptr = (uint8_t *)wmi_buf_data(buf);
  192. qdf_mem_zero(buf_ptr, len);
  193. cmd = (wmi_peer_smart_ant_set_tx_antenna_cmd_fixed_param *)buf_ptr;
  194. WMITLV_SET_HDR(&cmd->tlv_header,
  195. WMITLV_TAG_STRUC_wmi_peer_smart_ant_set_tx_antenna_cmd_fixed_param,
  196. WMITLV_GET_STRUCT_TLVLEN(
  197. wmi_peer_smart_ant_set_tx_antenna_cmd_fixed_param));
  198. cmd->vdev_id = param->vdev_id;
  199. WMI_CHAR_ARRAY_TO_MAC_ADDR(macaddr, &cmd->peer_macaddr);
  200. buf_ptr += sizeof(wmi_peer_smart_ant_set_tx_antenna_cmd_fixed_param);
  201. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  202. sizeof(wmi_peer_smart_ant_set_tx_antenna_series) *
  203. WMI_SMART_ANT_MAX_RATE_SERIES);
  204. buf_ptr += WMI_TLV_HDR_SIZE;
  205. ant_tx_series = (wmi_peer_smart_ant_set_tx_antenna_series *)buf_ptr;
  206. for (i = 0; i < WMI_SMART_ANT_MAX_RATE_SERIES; i++) {
  207. WMITLV_SET_HDR(&ant_tx_series->tlv_header,
  208. WMITLV_TAG_STRUC_wmi_peer_smart_ant_set_tx_antenna_series,
  209. WMITLV_GET_STRUCT_TLVLEN(
  210. wmi_peer_smart_ant_set_tx_antenna_series));
  211. ant_tx_series->antenna_series = param->antenna_array[i];
  212. ant_tx_series++;
  213. }
  214. wmi_mtrace(WMI_PEER_SMART_ANT_SET_TX_ANTENNA_CMDID, cmd->vdev_id, 0);
  215. ret = wmi_unified_cmd_send(wmi_handle,
  216. buf,
  217. len,
  218. WMI_PEER_SMART_ANT_SET_TX_ANTENNA_CMDID);
  219. if (ret != 0) {
  220. WMI_LOGE(" %s :WMI Failed\n", __func__);
  221. wmi_buf_free(buf);
  222. }
  223. return ret;
  224. }
  225. /**
  226. * send_set_ant_switch_tbl_cmd_tlv() - send ant switch tbl cmd to fw
  227. * @wmi_handle: wmi handle
  228. * @param: pointer to hold ant switch tbl param
  229. *
  230. * @return QDF_STATUS_SUCCESS on success and -ve on failure.
  231. */
  232. static QDF_STATUS
  233. send_set_ant_switch_tbl_cmd_tlv(wmi_unified_t wmi_handle,
  234. struct ant_switch_tbl_params *param)
  235. {
  236. uint8_t len;
  237. wmi_buf_t buf;
  238. wmi_pdev_set_ant_switch_tbl_cmd_fixed_param *cmd;
  239. wmi_pdev_set_ant_ctrl_chain *ctrl_chain;
  240. uint8_t *buf_ptr;
  241. len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
  242. len += sizeof(wmi_pdev_set_ant_ctrl_chain);
  243. buf = wmi_buf_alloc(wmi_handle, len);
  244. if (!buf) {
  245. WMI_LOGE("%s:wmi_buf_alloc failed\n", __func__);
  246. return QDF_STATUS_E_NOMEM;
  247. }
  248. buf_ptr = (uint8_t *)wmi_buf_data(buf);
  249. qdf_mem_zero(buf_ptr, len);
  250. cmd = (wmi_pdev_set_ant_switch_tbl_cmd_fixed_param *)buf_ptr;
  251. WMITLV_SET_HDR(&cmd->tlv_header,
  252. WMITLV_TAG_STRUC_wmi_pdev_set_ant_switch_tbl_cmd_fixed_param,
  253. WMITLV_GET_STRUCT_TLVLEN(
  254. wmi_pdev_set_ant_switch_tbl_cmd_fixed_param));
  255. cmd->antCtrlCommon1 = param->ant_ctrl_common1;
  256. cmd->antCtrlCommon2 = param->ant_ctrl_common2;
  257. cmd->mac_id =
  258. wmi_handle->ops->convert_pdev_id_host_to_target(
  259. wmi_handle,
  260. param->pdev_id);
  261. /* TLV indicating array of structures to follow */
  262. buf_ptr += sizeof(wmi_pdev_set_ant_switch_tbl_cmd_fixed_param);
  263. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  264. sizeof(wmi_pdev_set_ant_ctrl_chain));
  265. buf_ptr += WMI_TLV_HDR_SIZE;
  266. ctrl_chain = (wmi_pdev_set_ant_ctrl_chain *)buf_ptr;
  267. WMITLV_SET_HDR(&ctrl_chain->tlv_header,
  268. WMITLV_TAG_STRUC_wmi_pdev_set_ant_ctrl_chain,
  269. WMITLV_GET_STRUCT_TLVLEN(wmi_pdev_set_ant_ctrl_chain));
  270. ctrl_chain->pdev_id =
  271. wmi_handle->ops->convert_pdev_id_host_to_target(
  272. wmi_handle,
  273. param->pdev_id);
  274. ctrl_chain->antCtrlChain = param->antCtrlChain;
  275. wmi_mtrace(WMI_PDEV_SET_ANTENNA_SWITCH_TABLE_CMDID, NO_SESSION, 0);
  276. if (wmi_unified_cmd_send(wmi_handle, buf, len,
  277. WMI_PDEV_SET_ANTENNA_SWITCH_TABLE_CMDID)) {
  278. wmi_buf_free(buf);
  279. WMI_LOGE("%s :WMI Failed\n", __func__);
  280. return QDF_STATUS_E_FAILURE;
  281. }
  282. return QDF_STATUS_SUCCESS;
  283. }
  284. /**
  285. * send_smart_ant_set_training_info_cmd_tlv() - WMI set smart antenna
  286. * training information function
  287. * @param wmi_handle : handle to WMI.
  288. * @macaddr : vdev mac address
  289. * @param param : pointer to tx antenna param
  290. * @return QDF_STATUS_SUCCESS on success and -ve on failure.
  291. */
  292. static QDF_STATUS send_smart_ant_set_training_info_cmd_tlv(
  293. wmi_unified_t wmi_handle,
  294. uint8_t macaddr[QDF_MAC_ADDR_SIZE],
  295. struct smart_ant_training_info_params *param)
  296. {
  297. wmi_peer_smart_ant_set_train_antenna_cmd_fixed_param *cmd;
  298. wmi_peer_smart_ant_set_train_antenna_param *train_param;
  299. wmi_buf_t buf;
  300. uint8_t *buf_ptr;
  301. int32_t len = 0;
  302. QDF_STATUS ret;
  303. uint8_t loop = 0, itr = 0;
  304. len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
  305. len += (WMI_SMART_ANT_MAX_RATE_SERIES) *
  306. sizeof(wmi_peer_smart_ant_set_train_antenna_param);
  307. buf = wmi_buf_alloc(wmi_handle, len);
  308. if (!buf) {
  309. WMI_LOGE("%s:wmi_buf_alloc failed\n", __func__);
  310. return QDF_STATUS_E_NOMEM;
  311. }
  312. buf_ptr = (uint8_t *)wmi_buf_data(buf);
  313. qdf_mem_zero(buf_ptr, len);
  314. cmd = (wmi_peer_smart_ant_set_train_antenna_cmd_fixed_param *)buf_ptr;
  315. WMITLV_SET_HDR(&cmd->tlv_header,
  316. WMITLV_TAG_STRUC_wmi_peer_smart_ant_set_train_antenna_cmd_fixed_param,
  317. WMITLV_GET_STRUCT_TLVLEN(
  318. wmi_peer_smart_ant_set_train_antenna_cmd_fixed_param));
  319. cmd->vdev_id = param->vdev_id;
  320. WMI_CHAR_ARRAY_TO_MAC_ADDR(macaddr, &cmd->peer_macaddr);
  321. cmd->num_pkts = param->numpkts;
  322. buf_ptr += sizeof(wmi_peer_smart_ant_set_train_antenna_cmd_fixed_param);
  323. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  324. sizeof(wmi_peer_smart_ant_set_train_antenna_param) *
  325. WMI_SMART_ANT_MAX_RATE_SERIES);
  326. buf_ptr += WMI_TLV_HDR_SIZE;
  327. train_param = (wmi_peer_smart_ant_set_train_antenna_param *)buf_ptr;
  328. for (loop = 0; loop < WMI_SMART_ANT_MAX_RATE_SERIES; loop++) {
  329. WMITLV_SET_HDR(&train_param->tlv_header,
  330. WMITLV_TAG_STRUC_wmi_peer_smart_ant_set_train_antenna_param,
  331. WMITLV_GET_STRUCT_TLVLEN(
  332. wmi_peer_smart_ant_set_train_antenna_param));
  333. train_param->train_rate_series_lo =
  334. ((param->rate_array[itr] & SA_MASK_RCODE) |
  335. (param->rate_array[itr] & (SA_MASK_RCODE << 16)));
  336. train_param->train_rate_series_hi =
  337. ((param->rate_array[itr + 1] & SA_MASK_RCODE) |
  338. (param->rate_array[itr + 1] & (SA_MASK_RCODE << 16)));
  339. itr += 2;
  340. train_param->train_antenna_series = param->antenna_array[loop];
  341. train_param->rc_flags = 0;
  342. wmi_info("Series number:%d", loop);
  343. wmi_info("Rate [0x%02x] Tx_Antenna [0x%08x]",
  344. train_param->train_rate_series,
  345. train_param->train_antenna_series);
  346. train_param++;
  347. }
  348. wmi_mtrace(WMI_PEER_SMART_ANT_SET_TRAIN_INFO_CMDID, cmd->vdev_id, 0);
  349. ret = wmi_unified_cmd_send(wmi_handle,
  350. buf,
  351. len,
  352. WMI_PEER_SMART_ANT_SET_TRAIN_INFO_CMDID);
  353. if (ret != 0) {
  354. WMI_LOGE(" %s :WMI Failed\n", __func__);
  355. wmi_buf_free(buf);
  356. return QDF_STATUS_E_FAILURE;
  357. }
  358. return ret;
  359. }
  360. /**
  361. * send_smart_ant_set_node_config_cmd_tlv() - WMI set node
  362. * configuration function
  363. * @param wmi_handle : handle to WMI.
  364. * @macaddr : vdev mad address
  365. * @param param : pointer to tx antenna param
  366. *
  367. * @return QDF_STATUS_SUCCESS on success and -ve on failure.
  368. */
  369. static QDF_STATUS send_smart_ant_set_node_config_cmd_tlv(
  370. wmi_unified_t wmi_handle,
  371. uint8_t macaddr[QDF_MAC_ADDR_SIZE],
  372. struct smart_ant_node_config_params *param)
  373. {
  374. wmi_peer_smart_ant_set_node_config_ops_cmd_fixed_param *cmd;
  375. wmi_buf_t buf;
  376. uint8_t *buf_ptr;
  377. int32_t len = 0, args_tlv_len;
  378. int ret;
  379. int i = 0;
  380. uint32_t *node_config_args;
  381. args_tlv_len = WMI_TLV_HDR_SIZE + param->args_count * sizeof(uint32_t);
  382. len = sizeof(*cmd) + args_tlv_len;
  383. if (param->args_count == 0) {
  384. WMI_LOGE("%s: Can't send a command with %d arguments\n",
  385. __func__, param->args_count);
  386. return QDF_STATUS_E_FAILURE;
  387. }
  388. buf = wmi_buf_alloc(wmi_handle, len);
  389. if (!buf) {
  390. WMI_LOGE("%s:wmi_buf_alloc failed\n", __func__);
  391. return QDF_STATUS_E_NOMEM;
  392. }
  393. cmd = (wmi_peer_smart_ant_set_node_config_ops_cmd_fixed_param *)
  394. wmi_buf_data(buf);
  395. buf_ptr = (uint8_t *)cmd;
  396. WMITLV_SET_HDR(&cmd->tlv_header,
  397. WMITLV_TAG_STRUC_wmi_peer_smart_ant_set_node_config_ops_cmd_fixed_param,
  398. WMITLV_GET_STRUCT_TLVLEN(
  399. wmi_peer_smart_ant_set_node_config_ops_cmd_fixed_param));
  400. cmd->vdev_id = param->vdev_id;
  401. WMI_CHAR_ARRAY_TO_MAC_ADDR(macaddr, &cmd->peer_macaddr);
  402. cmd->cmd_id = param->cmd_id;
  403. cmd->args_count = param->args_count;
  404. buf_ptr += sizeof(
  405. wmi_peer_smart_ant_set_node_config_ops_cmd_fixed_param);
  406. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
  407. (cmd->args_count * sizeof(uint32_t)));
  408. buf_ptr += WMI_TLV_HDR_SIZE;
  409. node_config_args = (uint32_t *)buf_ptr;
  410. for (i = 0; i < param->args_count; i++) {
  411. node_config_args[i] = param->args_arr[i];
  412. wmi_info("%d", param->args_arr[i]);
  413. }
  414. wmi_mtrace(WMI_PEER_SMART_ANT_SET_NODE_CONFIG_OPS_CMDID,
  415. cmd->vdev_id, 0);
  416. ret = wmi_unified_cmd_send(wmi_handle,
  417. buf,
  418. len,
  419. WMI_PEER_SMART_ANT_SET_NODE_CONFIG_OPS_CMDID);
  420. if (ret != 0) {
  421. WMI_LOGE("%s: WMI FAILED:Sent cmd_id: 0x%x\n Node: %02x:%02x:%02x:%02x:%02x:%02x cmdstatus=%d\n",
  422. __func__, param->cmd_id, macaddr[0],
  423. macaddr[1], macaddr[2], macaddr[3],
  424. macaddr[4], macaddr[5], ret);
  425. wmi_buf_free(buf);
  426. }
  427. return ret;
  428. }
  429. /**
  430. * extract_peer_ratecode_list_ev_tlv() - extract peer ratecode from event
  431. * @wmi_handle: wmi handle
  432. * @param evt_buf: pointer to event buffer
  433. * @param peer_mac: Pointer to hold peer mac address
  434. * @param pdev_id: Pointer to pdev_id
  435. * @param rate_cap: Pointer to hold ratecode
  436. *
  437. * @return QDF_STATUS_SUCCESS on success or error code
  438. */
  439. static QDF_STATUS extract_peer_ratecode_list_ev_tlv(
  440. wmi_unified_t wmi_handle,
  441. void *evt_buf,
  442. uint8_t *peer_mac,
  443. uint32_t *pdev_id,
  444. wmi_sa_rate_cap *rate_cap)
  445. {
  446. WMI_PEER_RATECODE_LIST_EVENTID_param_tlvs *param_buf;
  447. wmi_peer_ratecode_list_event_fixed_param *ev;
  448. wmi_peer_cck_ofdm_rate_info *ofdm_rate;
  449. wmi_peer_mcs_rate_info *mcs_rate;
  450. uint8_t i, htindex, j;
  451. uint8_t shift = 0;
  452. param_buf = (WMI_PEER_RATECODE_LIST_EVENTID_param_tlvs *)evt_buf;
  453. ev = (wmi_peer_ratecode_list_event_fixed_param *)param_buf->fixed_param;
  454. WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, peer_mac);
  455. *pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host(wmi_handle,
  456. ev->pdev_id);
  457. for (i = 0; i < SA_BYTES_IN_DWORD; i++) {
  458. rate_cap->ratecount[i] = ((ev->ratecount >> (i*8)) &
  459. SA_MASK_BYTE);
  460. }
  461. htindex = 0;
  462. if (rate_cap->ratecount[0]) {
  463. if (param_buf->num_ratecode_legacy >
  464. SA_MAX_LEGACY_RATE_WORDS) {
  465. WMI_LOGE("Invalid Number of ratecode_legacy %d",
  466. param_buf->num_ratecode_legacy);
  467. return QDF_STATUS_E_FAILURE;
  468. }
  469. ofdm_rate = param_buf->ratecode_legacy;
  470. for (i = 0; i < param_buf->num_ratecode_legacy; i++) {
  471. for (j = 0; j < SA_WORDS_IN_DWORD; j++) {
  472. shift = (SA_WORD_BITS_LEN * j);
  473. rate_cap->ratecode_legacy[htindex] =
  474. ((ofdm_rate->ratecode_legacy >> shift) &
  475. SA_MASK_RCODE);
  476. htindex++;
  477. }
  478. ofdm_rate++;
  479. }
  480. }
  481. htindex = 0;
  482. if (param_buf->num_ratecode_mcs > SA_MAX_HT_RATE_WORDS) {
  483. WMI_LOGE("Invalid Number of ratecode_mcs %d",
  484. param_buf->num_ratecode_mcs);
  485. return QDF_STATUS_E_FAILURE;
  486. }
  487. mcs_rate = param_buf->ratecode_mcs;
  488. for (i = 0; i < param_buf->num_ratecode_mcs; i++) {
  489. for (j = 0; j < SA_WORDS_IN_DWORD; j++) {
  490. shift = (SA_WORD_BITS_LEN * j);
  491. rate_cap->ratecode_20[htindex] =
  492. ((mcs_rate->ratecode_20 >> (shift)) & SA_MASK_RCODE);
  493. rate_cap->ratecode_40[htindex] =
  494. ((mcs_rate->ratecode_40 >> (shift)) & SA_MASK_RCODE);
  495. rate_cap->ratecode_80[htindex] =
  496. ((mcs_rate->ratecode_80 >> (shift)) & SA_MASK_RCODE);
  497. htindex++;
  498. }
  499. mcs_rate++;
  500. }
  501. return QDF_STATUS_SUCCESS;
  502. }
  503. void wmi_smart_ant_attach_tlv(wmi_unified_t wmi_handle)
  504. {
  505. struct wmi_ops *ops = wmi_handle->ops;
  506. ops->send_smart_ant_enable_cmd = send_smart_ant_enable_cmd_tlv;
  507. ops->send_smart_ant_set_rx_ant_cmd = send_smart_ant_set_rx_ant_cmd_tlv;
  508. ops->send_smart_ant_set_tx_ant_cmd = send_smart_ant_set_tx_ant_cmd_tlv;
  509. ops->send_smart_ant_set_training_info_cmd =
  510. send_smart_ant_set_training_info_cmd_tlv;
  511. ops->send_smart_ant_set_node_config_cmd =
  512. send_smart_ant_set_node_config_cmd_tlv;
  513. ops->send_set_ant_switch_tbl_cmd = send_set_ant_switch_tbl_cmd_tlv;
  514. ops->extract_peer_ratecode_list_ev = extract_peer_ratecode_list_ev_tlv;
  515. }
  516. #endif