wmi_unified_cp_stats_tlv.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  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 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 "osdep.h"
  17. #include "wmi.h"
  18. #include "wmi_unified_priv.h"
  19. #include "wmi_unified_param.h"
  20. /**
  21. * send_stats_request_cmd_tlv() - WMI request stats function
  22. * @param wmi_handle: handle to WMI.
  23. * @param macaddr: MAC address
  24. * @param param: pointer to hold stats request parameter
  25. *
  26. * Return: 0 on success and -ve on failure.
  27. */
  28. static QDF_STATUS
  29. send_stats_request_cmd_tlv(wmi_unified_t wmi_handle,
  30. uint8_t macaddr[QDF_MAC_ADDR_SIZE],
  31. struct stats_request_params *param)
  32. {
  33. int32_t ret;
  34. wmi_request_stats_cmd_fixed_param *cmd;
  35. wmi_buf_t buf;
  36. uint16_t len = sizeof(wmi_request_stats_cmd_fixed_param);
  37. buf = wmi_buf_alloc(wmi_handle, len);
  38. if (!buf)
  39. return QDF_STATUS_E_NOMEM;
  40. cmd = (wmi_request_stats_cmd_fixed_param *) wmi_buf_data(buf);
  41. WMITLV_SET_HDR(&cmd->tlv_header,
  42. WMITLV_TAG_STRUC_wmi_request_stats_cmd_fixed_param,
  43. WMITLV_GET_STRUCT_TLVLEN
  44. (wmi_request_stats_cmd_fixed_param));
  45. cmd->stats_id = param->stats_id;
  46. cmd->vdev_id = param->vdev_id;
  47. cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
  48. wmi_handle,
  49. param->pdev_id);
  50. WMI_CHAR_ARRAY_TO_MAC_ADDR(macaddr, &cmd->peer_macaddr);
  51. WMI_LOGD("STATS REQ STATS_ID:%d VDEV_ID:%d PDEV_ID:%d-->",
  52. cmd->stats_id, cmd->vdev_id, cmd->pdev_id);
  53. wmi_mtrace(WMI_REQUEST_STATS_CMDID, cmd->vdev_id, 0);
  54. ret = wmi_unified_cmd_send_pm_chk(wmi_handle, buf, len,
  55. WMI_REQUEST_STATS_CMDID);
  56. if (ret) {
  57. WMI_LOGE("Failed to send status request to fw =%d", ret);
  58. wmi_buf_free(buf);
  59. }
  60. return qdf_status_from_os_return(ret);
  61. }
  62. /**
  63. * extract_all_stats_counts_tlv() - extract all stats count from event
  64. * @param wmi_handle: wmi handle
  65. * @param evt_buf: pointer to event buffer
  66. * @param stats_param: Pointer to hold stats count
  67. *
  68. * Return: QDF_STATUS_SUCCESS for success or error code
  69. */
  70. static QDF_STATUS
  71. extract_all_stats_counts_tlv(wmi_unified_t wmi_handle, void *evt_buf,
  72. wmi_host_stats_event *stats_param)
  73. {
  74. wmi_stats_event_fixed_param *ev;
  75. wmi_per_chain_rssi_stats *rssi_event;
  76. WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
  77. uint64_t min_data_len;
  78. qdf_mem_zero(stats_param, sizeof(*stats_param));
  79. param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf;
  80. ev = (wmi_stats_event_fixed_param *) param_buf->fixed_param;
  81. rssi_event = param_buf->chain_stats;
  82. if (!ev) {
  83. WMI_LOGE("%s: event fixed param NULL", __func__);
  84. return QDF_STATUS_E_FAILURE;
  85. }
  86. if (param_buf->num_data > WMI_SVC_MSG_MAX_SIZE - sizeof(*ev)) {
  87. WMI_LOGE("num_data : %u is invalid", param_buf->num_data);
  88. return QDF_STATUS_E_FAULT;
  89. }
  90. switch (ev->stats_id) {
  91. case WMI_REQUEST_PEER_STAT:
  92. stats_param->stats_id |= WMI_HOST_REQUEST_PEER_STAT;
  93. break;
  94. case WMI_REQUEST_AP_STAT:
  95. stats_param->stats_id |= WMI_HOST_REQUEST_AP_STAT;
  96. break;
  97. case WMI_REQUEST_PDEV_STAT:
  98. stats_param->stats_id |= WMI_HOST_REQUEST_PDEV_STAT;
  99. break;
  100. case WMI_REQUEST_VDEV_STAT:
  101. stats_param->stats_id |= WMI_HOST_REQUEST_VDEV_STAT;
  102. break;
  103. case WMI_REQUEST_BCNFLT_STAT:
  104. stats_param->stats_id |= WMI_HOST_REQUEST_BCNFLT_STAT;
  105. break;
  106. case WMI_REQUEST_VDEV_RATE_STAT:
  107. stats_param->stats_id |= WMI_HOST_REQUEST_VDEV_RATE_STAT;
  108. break;
  109. case WMI_REQUEST_BCN_STAT:
  110. stats_param->stats_id |= WMI_HOST_REQUEST_BCN_STAT;
  111. break;
  112. case WMI_REQUEST_PEER_EXTD_STAT:
  113. stats_param->stats_id |= WMI_REQUEST_PEER_EXTD_STAT;
  114. break;
  115. case WMI_REQUEST_PEER_EXTD2_STAT:
  116. stats_param->stats_id |= WMI_HOST_REQUEST_PEER_ADV_STATS;
  117. break;
  118. default:
  119. stats_param->stats_id = 0;
  120. break;
  121. }
  122. /* ev->num_*_stats may cause uint32_t overflow, so use uint64_t
  123. * to save total length calculated
  124. */
  125. min_data_len =
  126. (((uint64_t)ev->num_pdev_stats) * sizeof(wmi_pdev_stats)) +
  127. (((uint64_t)ev->num_vdev_stats) * sizeof(wmi_vdev_stats)) +
  128. (((uint64_t)ev->num_peer_stats) * sizeof(wmi_peer_stats)) +
  129. (((uint64_t)ev->num_bcnflt_stats) *
  130. sizeof(wmi_bcnfilter_stats_t)) +
  131. (((uint64_t)ev->num_chan_stats) * sizeof(wmi_chan_stats)) +
  132. (((uint64_t)ev->num_mib_stats) * sizeof(wmi_mib_stats)) +
  133. (((uint64_t)ev->num_bcn_stats) * sizeof(wmi_bcn_stats)) +
  134. (((uint64_t)ev->num_peer_extd_stats) *
  135. sizeof(wmi_peer_extd_stats)) +
  136. (((uint64_t)ev->num_mib_extd_stats) *
  137. sizeof(wmi_mib_extd_stats));
  138. if (param_buf->num_data != min_data_len) {
  139. WMI_LOGE("data len: %u isn't same as calculated: %llu",
  140. param_buf->num_data, min_data_len);
  141. return QDF_STATUS_E_FAULT;
  142. }
  143. stats_param->last_event = ev->last_event;
  144. stats_param->num_pdev_stats = ev->num_pdev_stats;
  145. stats_param->num_pdev_ext_stats = 0;
  146. stats_param->num_vdev_stats = ev->num_vdev_stats;
  147. stats_param->num_peer_stats = ev->num_peer_stats;
  148. stats_param->num_peer_extd_stats = ev->num_peer_extd_stats;
  149. stats_param->num_bcnflt_stats = ev->num_bcnflt_stats;
  150. stats_param->num_chan_stats = ev->num_chan_stats;
  151. stats_param->num_mib_stats = ev->num_mib_stats;
  152. stats_param->num_mib_extd_stats = ev->num_mib_extd_stats;
  153. stats_param->num_bcn_stats = ev->num_bcn_stats;
  154. stats_param->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host(
  155. wmi_handle,
  156. ev->pdev_id);
  157. /* if chain_stats is not populated */
  158. if (!param_buf->chain_stats || !param_buf->num_chain_stats)
  159. return QDF_STATUS_SUCCESS;
  160. if (WMITLV_TAG_STRUC_wmi_per_chain_rssi_stats !=
  161. WMITLV_GET_TLVTAG(rssi_event->tlv_header))
  162. return QDF_STATUS_SUCCESS;
  163. if (WMITLV_GET_STRUCT_TLVLEN(wmi_per_chain_rssi_stats) !=
  164. WMITLV_GET_TLVLEN(rssi_event->tlv_header))
  165. return QDF_STATUS_SUCCESS;
  166. if (rssi_event->num_per_chain_rssi_stats >=
  167. WMITLV_GET_TLVLEN(rssi_event->tlv_header)) {
  168. WMI_LOGE("num_per_chain_rssi_stats:%u is out of bounds",
  169. rssi_event->num_per_chain_rssi_stats);
  170. return QDF_STATUS_E_INVAL;
  171. }
  172. stats_param->num_rssi_stats = rssi_event->num_per_chain_rssi_stats;
  173. /* if peer_adv_stats is not populated */
  174. if (!param_buf->num_peer_extd2_stats)
  175. return QDF_STATUS_SUCCESS;
  176. stats_param->num_peer_adv_stats = param_buf->num_peer_extd2_stats;
  177. return QDF_STATUS_SUCCESS;
  178. }
  179. /**
  180. * extract_pdev_tx_stats() - extract pdev tx stats from event
  181. */
  182. static void extract_pdev_tx_stats(wmi_host_dbg_tx_stats *tx,
  183. struct wlan_dbg_tx_stats *tx_stats)
  184. {
  185. /* Tx Stats */
  186. tx->comp_queued = tx_stats->comp_queued;
  187. tx->comp_delivered = tx_stats->comp_delivered;
  188. tx->msdu_enqued = tx_stats->msdu_enqued;
  189. tx->mpdu_enqued = tx_stats->mpdu_enqued;
  190. tx->wmm_drop = tx_stats->wmm_drop;
  191. tx->local_enqued = tx_stats->local_enqued;
  192. tx->local_freed = tx_stats->local_freed;
  193. tx->hw_queued = tx_stats->hw_queued;
  194. tx->hw_reaped = tx_stats->hw_reaped;
  195. tx->underrun = tx_stats->underrun;
  196. tx->tx_abort = tx_stats->tx_abort;
  197. tx->mpdus_requed = tx_stats->mpdus_requed;
  198. tx->data_rc = tx_stats->data_rc;
  199. tx->self_triggers = tx_stats->self_triggers;
  200. tx->sw_retry_failure = tx_stats->sw_retry_failure;
  201. tx->illgl_rate_phy_err = tx_stats->illgl_rate_phy_err;
  202. tx->pdev_cont_xretry = tx_stats->pdev_cont_xretry;
  203. tx->pdev_tx_timeout = tx_stats->pdev_tx_timeout;
  204. tx->pdev_resets = tx_stats->pdev_resets;
  205. tx->stateless_tid_alloc_failure = tx_stats->stateless_tid_alloc_failure;
  206. tx->phy_underrun = tx_stats->phy_underrun;
  207. tx->txop_ovf = tx_stats->txop_ovf;
  208. return;
  209. }
  210. /**
  211. * extract_pdev_rx_stats() - extract pdev rx stats from event
  212. */
  213. static void extract_pdev_rx_stats(wmi_host_dbg_rx_stats *rx,
  214. struct wlan_dbg_rx_stats *rx_stats)
  215. {
  216. /* Rx Stats */
  217. rx->mid_ppdu_route_change = rx_stats->mid_ppdu_route_change;
  218. rx->status_rcvd = rx_stats->status_rcvd;
  219. rx->r0_frags = rx_stats->r0_frags;
  220. rx->r1_frags = rx_stats->r1_frags;
  221. rx->r2_frags = rx_stats->r2_frags;
  222. /* Only TLV */
  223. rx->r3_frags = 0;
  224. rx->htt_msdus = rx_stats->htt_msdus;
  225. rx->htt_mpdus = rx_stats->htt_mpdus;
  226. rx->loc_msdus = rx_stats->loc_msdus;
  227. rx->loc_mpdus = rx_stats->loc_mpdus;
  228. rx->oversize_amsdu = rx_stats->oversize_amsdu;
  229. rx->phy_errs = rx_stats->phy_errs;
  230. rx->phy_err_drop = rx_stats->phy_err_drop;
  231. rx->mpdu_errs = rx_stats->mpdu_errs;
  232. return;
  233. }
  234. /**
  235. * extract_pdev_stats_tlv() - extract pdev stats from event
  236. * @param wmi_handle: wmi handle
  237. * @param evt_buf: pointer to event buffer
  238. * @param index: Index into pdev stats
  239. * @param pdev_stats: Pointer to hold pdev stats
  240. *
  241. * Return: QDF_STATUS_SUCCESS for success or error code
  242. */
  243. static QDF_STATUS
  244. extract_pdev_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t index,
  245. wmi_host_pdev_stats *pdev_stats)
  246. {
  247. WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
  248. wmi_stats_event_fixed_param *ev_param;
  249. uint8_t *data;
  250. param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf;
  251. ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param;
  252. data = param_buf->data;
  253. if (index < ev_param->num_pdev_stats) {
  254. wmi_pdev_stats *ev = (wmi_pdev_stats *) ((data) +
  255. (index * sizeof(wmi_pdev_stats)));
  256. pdev_stats->chan_nf = ev->chan_nf;
  257. pdev_stats->tx_frame_count = ev->tx_frame_count;
  258. pdev_stats->rx_frame_count = ev->rx_frame_count;
  259. pdev_stats->rx_clear_count = ev->rx_clear_count;
  260. pdev_stats->cycle_count = ev->cycle_count;
  261. pdev_stats->phy_err_count = ev->phy_err_count;
  262. pdev_stats->chan_tx_pwr = ev->chan_tx_pwr;
  263. extract_pdev_tx_stats(&(pdev_stats->pdev_stats.tx),
  264. &(ev->pdev_stats.tx));
  265. extract_pdev_rx_stats(&(pdev_stats->pdev_stats.rx),
  266. &(ev->pdev_stats.rx));
  267. }
  268. return QDF_STATUS_SUCCESS;
  269. }
  270. /**
  271. * extract_vdev_stats_tlv() - extract vdev stats from event
  272. * @param wmi_handle: wmi handle
  273. * @param evt_buf: pointer to event buffer
  274. * @param index: Index into vdev stats
  275. * @param vdev_stats: Pointer to hold vdev stats
  276. *
  277. * Return: QDF_STATUS_SUCCESS for success or error code
  278. */
  279. static QDF_STATUS extract_vdev_stats_tlv(wmi_unified_t wmi_handle,
  280. void *evt_buf, uint32_t index, wmi_host_vdev_stats *vdev_stats)
  281. {
  282. WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
  283. wmi_stats_event_fixed_param *ev_param;
  284. uint8_t *data;
  285. param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf;
  286. ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param;
  287. data = (uint8_t *) param_buf->data;
  288. if (index < ev_param->num_vdev_stats) {
  289. wmi_vdev_stats *ev = (wmi_vdev_stats *) ((data) +
  290. ((ev_param->num_pdev_stats) *
  291. sizeof(wmi_pdev_stats)) +
  292. (index * sizeof(wmi_vdev_stats)));
  293. vdev_stats->vdev_id = ev->vdev_id;
  294. vdev_stats->vdev_snr.bcn_snr = ev->vdev_snr.bcn_snr;
  295. vdev_stats->vdev_snr.dat_snr = ev->vdev_snr.dat_snr;
  296. OS_MEMCPY(vdev_stats->tx_frm_cnt, ev->tx_frm_cnt,
  297. sizeof(ev->tx_frm_cnt));
  298. vdev_stats->rx_frm_cnt = ev->rx_frm_cnt;
  299. OS_MEMCPY(vdev_stats->multiple_retry_cnt,
  300. ev->multiple_retry_cnt,
  301. sizeof(ev->multiple_retry_cnt));
  302. OS_MEMCPY(vdev_stats->fail_cnt, ev->fail_cnt,
  303. sizeof(ev->fail_cnt));
  304. vdev_stats->rts_fail_cnt = ev->rts_fail_cnt;
  305. vdev_stats->rts_succ_cnt = ev->rts_succ_cnt;
  306. vdev_stats->rx_err_cnt = ev->rx_err_cnt;
  307. vdev_stats->rx_discard_cnt = ev->rx_discard_cnt;
  308. vdev_stats->ack_fail_cnt = ev->ack_fail_cnt;
  309. OS_MEMCPY(vdev_stats->tx_rate_history, ev->tx_rate_history,
  310. sizeof(ev->tx_rate_history));
  311. OS_MEMCPY(vdev_stats->bcn_rssi_history, ev->bcn_rssi_history,
  312. sizeof(ev->bcn_rssi_history));
  313. }
  314. return QDF_STATUS_SUCCESS;
  315. }
  316. /**
  317. * extract_peer_stats_tlv() - extract peer stats from event
  318. * @param wmi_handle: wmi handle
  319. * @param evt_buf: pointer to event buffer
  320. * @param index: Index into peer stats
  321. * @param peer_stats: Pointer to hold peer stats
  322. *
  323. * Return: QDF_STATUS_SUCCESS for success or error code
  324. */
  325. static QDF_STATUS
  326. extract_peer_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t index,
  327. wmi_host_peer_stats *peer_stats)
  328. {
  329. WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
  330. wmi_stats_event_fixed_param *ev_param;
  331. uint8_t *data;
  332. param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *) evt_buf;
  333. ev_param = (wmi_stats_event_fixed_param *) param_buf->fixed_param;
  334. data = (uint8_t *) param_buf->data;
  335. if (index < ev_param->num_peer_stats) {
  336. wmi_peer_stats *ev = (wmi_peer_stats *) ((data) +
  337. ((ev_param->num_pdev_stats) * sizeof(wmi_pdev_stats)) +
  338. ((ev_param->num_vdev_stats) * sizeof(wmi_vdev_stats)) +
  339. (index * sizeof(wmi_peer_stats)));
  340. OS_MEMSET(peer_stats, 0, sizeof(wmi_host_peer_stats));
  341. OS_MEMCPY(&(peer_stats->peer_macaddr),
  342. &(ev->peer_macaddr), sizeof(wmi_mac_addr));
  343. peer_stats->peer_rssi = ev->peer_rssi;
  344. peer_stats->peer_tx_rate = ev->peer_tx_rate;
  345. peer_stats->peer_rx_rate = ev->peer_rx_rate;
  346. }
  347. return QDF_STATUS_SUCCESS;
  348. }
  349. /**
  350. * extract_peer_extd_stats_tlv() - extract extended peer stats from event
  351. * @param wmi_handle: wmi handle
  352. * @param evt_buf: pointer to event buffer
  353. * @param index: Index into extended peer stats
  354. * @param peer_extd_stats: Pointer to hold extended peer stats
  355. *
  356. * Return: QDF_STATUS_SUCCESS for success or error code
  357. */
  358. static QDF_STATUS
  359. extract_peer_extd_stats_tlv(wmi_unified_t wmi_handle,
  360. void *evt_buf, uint32_t index,
  361. wmi_host_peer_extd_stats *peer_extd_stats)
  362. {
  363. WMI_UPDATE_STATS_EVENTID_param_tlvs *param_buf;
  364. wmi_stats_event_fixed_param *ev_param;
  365. uint8_t *data;
  366. param_buf = (WMI_UPDATE_STATS_EVENTID_param_tlvs *)evt_buf;
  367. ev_param = (wmi_stats_event_fixed_param *)param_buf->fixed_param;
  368. data = (uint8_t *)param_buf->data;
  369. if (!data)
  370. return QDF_STATUS_E_FAILURE;
  371. if (index < ev_param->num_peer_extd_stats) {
  372. wmi_peer_extd_stats *ev = (wmi_peer_extd_stats *) (data +
  373. (ev_param->num_pdev_stats * sizeof(wmi_pdev_stats)) +
  374. (ev_param->num_vdev_stats * sizeof(wmi_vdev_stats)) +
  375. (ev_param->num_peer_stats * sizeof(wmi_peer_stats)) +
  376. (ev_param->num_bcnflt_stats *
  377. sizeof(wmi_bcnfilter_stats_t)) +
  378. (ev_param->num_chan_stats * sizeof(wmi_chan_stats)) +
  379. (ev_param->num_mib_stats * sizeof(wmi_mib_stats)) +
  380. (ev_param->num_bcn_stats * sizeof(wmi_bcn_stats)) +
  381. (index * sizeof(wmi_peer_extd_stats)));
  382. qdf_mem_zero(peer_extd_stats, sizeof(wmi_host_peer_extd_stats));
  383. qdf_mem_copy(&peer_extd_stats->peer_macaddr, &ev->peer_macaddr,
  384. sizeof(wmi_mac_addr));
  385. peer_extd_stats->rx_mc_bc_cnt = ev->rx_mc_bc_cnt;
  386. }
  387. return QDF_STATUS_SUCCESS;
  388. }
  389. void wmi_cp_stats_attach_tlv(wmi_unified_t wmi_handle)
  390. {
  391. struct wmi_ops *ops = wmi_handle->ops;
  392. ops->send_stats_request_cmd = send_stats_request_cmd_tlv;
  393. ops->extract_all_stats_count = extract_all_stats_counts_tlv;
  394. ops->extract_pdev_stats = extract_pdev_stats_tlv;
  395. ops->extract_vdev_stats = extract_vdev_stats_tlv;
  396. ops->extract_peer_stats = extract_peer_stats_tlv;
  397. ops->extract_peer_extd_stats = extract_peer_extd_stats_tlv;
  398. wmi_mc_cp_stats_attach_tlv(wmi_handle);
  399. }