305-ath10k-add-fw_stats-support-to-10.4-firmware.patch 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. From: Manikanta Pubbisetty <[email protected]>
  2. Date: Wed, 28 Oct 2015 21:38:33 +0200
  3. Subject: [PATCH] ath10k: add fw_stats support to 10.4 firmware
  4. This patch adds support for getting firmware debug stats in 10.4 fw.
  5. Signed-off-by: Manikanta Pubbisetty <[email protected]>
  6. Signed-off-by: Tamizh chelvam <[email protected]>
  7. Signed-off-by: Kalle Valo <[email protected]>
  8. ---
  9. --- a/drivers/net/wireless/ath/ath10k/core.h
  10. +++ b/drivers/net/wireless/ath/ath10k/core.h
  11. @@ -214,6 +214,7 @@ struct ath10k_fw_stats_pdev {
  12. s32 hw_queued;
  13. s32 hw_reaped;
  14. s32 underrun;
  15. + u32 hw_paused;
  16. s32 tx_abort;
  17. s32 mpdus_requed;
  18. u32 tx_ko;
  19. @@ -226,6 +227,16 @@ struct ath10k_fw_stats_pdev {
  20. u32 pdev_resets;
  21. u32 phy_underrun;
  22. u32 txop_ovf;
  23. + u32 seq_posted;
  24. + u32 seq_failed_queueing;
  25. + u32 seq_completed;
  26. + u32 seq_restarted;
  27. + u32 mu_seq_posted;
  28. + u32 mpdus_sw_flush;
  29. + u32 mpdus_hw_filter;
  30. + u32 mpdus_truncated;
  31. + u32 mpdus_ack_failed;
  32. + u32 mpdus_expired;
  33. /* PDEV RX stats */
  34. s32 mid_ppdu_route_change;
  35. @@ -242,6 +253,7 @@ struct ath10k_fw_stats_pdev {
  36. s32 phy_errs;
  37. s32 phy_err_drop;
  38. s32 mpdu_errs;
  39. + s32 rx_ovfl_errs;
  40. };
  41. struct ath10k_fw_stats {
  42. --- a/drivers/net/wireless/ath/ath10k/wmi.c
  43. +++ b/drivers/net/wireless/ath/ath10k/wmi.c
  44. @@ -2479,6 +2479,47 @@ void ath10k_wmi_pull_pdev_stats_tx(const
  45. dst->txop_ovf = __le32_to_cpu(src->txop_ovf);
  46. }
  47. +static void
  48. +ath10k_wmi_10_4_pull_pdev_stats_tx(const struct wmi_10_4_pdev_stats_tx *src,
  49. + struct ath10k_fw_stats_pdev *dst)
  50. +{
  51. + dst->comp_queued = __le32_to_cpu(src->comp_queued);
  52. + dst->comp_delivered = __le32_to_cpu(src->comp_delivered);
  53. + dst->msdu_enqued = __le32_to_cpu(src->msdu_enqued);
  54. + dst->mpdu_enqued = __le32_to_cpu(src->mpdu_enqued);
  55. + dst->wmm_drop = __le32_to_cpu(src->wmm_drop);
  56. + dst->local_enqued = __le32_to_cpu(src->local_enqued);
  57. + dst->local_freed = __le32_to_cpu(src->local_freed);
  58. + dst->hw_queued = __le32_to_cpu(src->hw_queued);
  59. + dst->hw_reaped = __le32_to_cpu(src->hw_reaped);
  60. + dst->underrun = __le32_to_cpu(src->underrun);
  61. + dst->tx_abort = __le32_to_cpu(src->tx_abort);
  62. + dst->mpdus_requed = __le32_to_cpu(src->mpdus_requed);
  63. + dst->tx_ko = __le32_to_cpu(src->tx_ko);
  64. + dst->data_rc = __le32_to_cpu(src->data_rc);
  65. + dst->self_triggers = __le32_to_cpu(src->self_triggers);
  66. + dst->sw_retry_failure = __le32_to_cpu(src->sw_retry_failure);
  67. + dst->illgl_rate_phy_err = __le32_to_cpu(src->illgl_rate_phy_err);
  68. + dst->pdev_cont_xretry = __le32_to_cpu(src->pdev_cont_xretry);
  69. + dst->pdev_tx_timeout = __le32_to_cpu(src->pdev_tx_timeout);
  70. + dst->pdev_resets = __le32_to_cpu(src->pdev_resets);
  71. + dst->phy_underrun = __le32_to_cpu(src->phy_underrun);
  72. + dst->txop_ovf = __le32_to_cpu(src->txop_ovf);
  73. + dst->hw_paused = __le32_to_cpu(src->hw_paused);
  74. + dst->seq_posted = __le32_to_cpu(src->seq_posted);
  75. + dst->seq_failed_queueing =
  76. + __le32_to_cpu(src->seq_failed_queueing);
  77. + dst->seq_completed = __le32_to_cpu(src->seq_completed);
  78. + dst->seq_restarted = __le32_to_cpu(src->seq_restarted);
  79. + dst->mu_seq_posted = __le32_to_cpu(src->mu_seq_posted);
  80. + dst->mpdus_sw_flush = __le32_to_cpu(src->mpdus_sw_flush);
  81. + dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter);
  82. + dst->mpdus_truncated = __le32_to_cpu(src->mpdus_truncated);
  83. + dst->mpdus_ack_failed = __le32_to_cpu(src->mpdus_ack_failed);
  84. + dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter);
  85. + dst->mpdus_expired = __le32_to_cpu(src->mpdus_expired);
  86. +}
  87. +
  88. void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src,
  89. struct ath10k_fw_stats_pdev *dst)
  90. {
  91. @@ -2789,6 +2830,86 @@ static int ath10k_wmi_10_2_4_op_pull_fw_
  92. return 0;
  93. }
  94. +static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
  95. + struct sk_buff *skb,
  96. + struct ath10k_fw_stats *stats)
  97. +{
  98. + const struct wmi_10_2_stats_event *ev = (void *)skb->data;
  99. + u32 num_pdev_stats;
  100. + u32 num_pdev_ext_stats;
  101. + u32 num_vdev_stats;
  102. + u32 num_peer_stats;
  103. + int i;
  104. +
  105. + if (!skb_pull(skb, sizeof(*ev)))
  106. + return -EPROTO;
  107. +
  108. + num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
  109. + num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats);
  110. + num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
  111. + num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
  112. +
  113. + for (i = 0; i < num_pdev_stats; i++) {
  114. + const struct wmi_10_4_pdev_stats *src;
  115. + struct ath10k_fw_stats_pdev *dst;
  116. +
  117. + src = (void *)skb->data;
  118. + if (!skb_pull(skb, sizeof(*src)))
  119. + return -EPROTO;
  120. +
  121. + dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
  122. + if (!dst)
  123. + continue;
  124. +
  125. + ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
  126. + ath10k_wmi_10_4_pull_pdev_stats_tx(&src->tx, dst);
  127. + ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
  128. + dst->rx_ovfl_errs = __le32_to_cpu(src->rx_ovfl_errs);
  129. + ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst);
  130. +
  131. + list_add_tail(&dst->list, &stats->pdevs);
  132. + }
  133. +
  134. + for (i = 0; i < num_pdev_ext_stats; i++) {
  135. + const struct wmi_10_2_pdev_ext_stats *src;
  136. +
  137. + src = (void *)skb->data;
  138. + if (!skb_pull(skb, sizeof(*src)))
  139. + return -EPROTO;
  140. +
  141. + /* FIXME: expose values to userspace
  142. + *
  143. + * Note: Even though this loop seems to do nothing it is
  144. + * required to parse following sub-structures properly.
  145. + */
  146. + }
  147. +
  148. + /* fw doesn't implement vdev stats */
  149. +
  150. + for (i = 0; i < num_peer_stats; i++) {
  151. + const struct wmi_10_4_peer_stats *src;
  152. + struct ath10k_fw_stats_peer *dst;
  153. +
  154. + src = (void *)skb->data;
  155. + if (!skb_pull(skb, sizeof(*src)))
  156. + return -EPROTO;
  157. +
  158. + dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
  159. + if (!dst)
  160. + continue;
  161. +
  162. + ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
  163. + dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
  164. + dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
  165. + dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
  166. + /* FIXME: expose 10.4 specific values */
  167. +
  168. + list_add_tail(&dst->list, &stats->peers);
  169. + }
  170. +
  171. + return 0;
  172. +}
  173. +
  174. void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb)
  175. {
  176. ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n");
  177. @@ -4935,6 +5056,9 @@ static void ath10k_wmi_10_4_op_rx(struct
  178. ath10k_dbg(ar, ATH10K_DBG_WMI,
  179. "received event id %d not implemented\n", id);
  180. break;
  181. + case WMI_10_4_UPDATE_STATS_EVENTID:
  182. + ath10k_wmi_event_update_stats(ar, skb);
  183. + break;
  184. default:
  185. ath10k_warn(ar, "Unknown eventid: %d\n", id);
  186. break;
  187. @@ -7022,6 +7146,90 @@ ath10k_wmi_op_gen_pdev_enable_adaptive_c
  188. return skb;
  189. }
  190. +void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
  191. + struct ath10k_fw_stats *fw_stats,
  192. + char *buf)
  193. +{
  194. + u32 len = 0;
  195. + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
  196. + const struct ath10k_fw_stats_pdev *pdev;
  197. + const struct ath10k_fw_stats_vdev *vdev;
  198. + const struct ath10k_fw_stats_peer *peer;
  199. + size_t num_peers;
  200. + size_t num_vdevs;
  201. +
  202. + spin_lock_bh(&ar->data_lock);
  203. +
  204. + pdev = list_first_entry_or_null(&fw_stats->pdevs,
  205. + struct ath10k_fw_stats_pdev, list);
  206. + if (!pdev) {
  207. + ath10k_warn(ar, "failed to get pdev stats\n");
  208. + goto unlock;
  209. + }
  210. +
  211. + num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
  212. + num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
  213. +
  214. + ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
  215. + ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
  216. + ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
  217. +
  218. + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
  219. + "HW paused", pdev->hw_paused);
  220. + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
  221. + "Seqs posted", pdev->seq_posted);
  222. + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
  223. + "Seqs failed queueing", pdev->seq_failed_queueing);
  224. + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
  225. + "Seqs completed", pdev->seq_completed);
  226. + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
  227. + "Seqs restarted", pdev->seq_restarted);
  228. + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
  229. + "MU Seqs posted", pdev->mu_seq_posted);
  230. + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
  231. + "MPDUs SW flushed", pdev->mpdus_sw_flush);
  232. + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
  233. + "MPDUs HW filtered", pdev->mpdus_hw_filter);
  234. + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
  235. + "MPDUs truncated", pdev->mpdus_truncated);
  236. + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
  237. + "MPDUs receive no ACK", pdev->mpdus_ack_failed);
  238. + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
  239. + "MPDUs expired", pdev->mpdus_expired);
  240. +
  241. + ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len);
  242. + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
  243. + "Num Rx Overflow errors", pdev->rx_ovfl_errs);
  244. +
  245. + len += scnprintf(buf + len, buf_len - len, "\n");
  246. + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
  247. + "ath10k VDEV stats", num_vdevs);
  248. + len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
  249. + "=================");
  250. +
  251. + list_for_each_entry(vdev, &fw_stats->vdevs, list) {
  252. + ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len);
  253. + }
  254. +
  255. + len += scnprintf(buf + len, buf_len - len, "\n");
  256. + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
  257. + "ath10k PEER stats", num_peers);
  258. + len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
  259. + "=================");
  260. +
  261. + list_for_each_entry(peer, &fw_stats->peers, list) {
  262. + ath10k_wmi_fw_peer_stats_fill(peer, buf, &len);
  263. + }
  264. +
  265. +unlock:
  266. + spin_unlock_bh(&ar->data_lock);
  267. +
  268. + if (len >= buf_len)
  269. + buf[len - 1] = 0;
  270. + else
  271. + buf[len] = 0;
  272. +}
  273. +
  274. static const struct wmi_ops wmi_ops = {
  275. .rx = ath10k_wmi_op_rx,
  276. .map_svc = wmi_main_svc_map,
  277. @@ -7292,6 +7500,7 @@ static const struct wmi_ops wmi_10_4_ops
  278. .rx = ath10k_wmi_10_4_op_rx,
  279. .map_svc = wmi_10_4_svc_map,
  280. + .pull_fw_stats = ath10k_wmi_10_4_op_pull_fw_stats,
  281. .pull_scan = ath10k_wmi_op_pull_scan_ev,
  282. .pull_mgmt_rx = ath10k_wmi_10_4_op_pull_mgmt_rx_ev,
  283. .pull_ch_info = ath10k_wmi_10_4_op_pull_ch_info_ev,
  284. @@ -7341,9 +7550,11 @@ static const struct wmi_ops wmi_10_4_ops
  285. .gen_addba_send = ath10k_wmi_op_gen_addba_send,
  286. .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
  287. .gen_delba_send = ath10k_wmi_op_gen_delba_send,
  288. + .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill,
  289. /* shared with 10.2 */
  290. .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
  291. + .gen_request_stats = ath10k_wmi_op_gen_request_stats,
  292. };
  293. int ath10k_wmi_attach(struct ath10k *ar)
  294. --- a/drivers/net/wireless/ath/ath10k/wmi.h
  295. +++ b/drivers/net/wireless/ath/ath10k/wmi.h
  296. @@ -3866,6 +3866,111 @@ struct wmi_pdev_stats_tx {
  297. __le32 txop_ovf;
  298. } __packed;
  299. +struct wmi_10_4_pdev_stats_tx {
  300. + /* Num HTT cookies queued to dispatch list */
  301. + __le32 comp_queued;
  302. +
  303. + /* Num HTT cookies dispatched */
  304. + __le32 comp_delivered;
  305. +
  306. + /* Num MSDU queued to WAL */
  307. + __le32 msdu_enqued;
  308. +
  309. + /* Num MPDU queue to WAL */
  310. + __le32 mpdu_enqued;
  311. +
  312. + /* Num MSDUs dropped by WMM limit */
  313. + __le32 wmm_drop;
  314. +
  315. + /* Num Local frames queued */
  316. + __le32 local_enqued;
  317. +
  318. + /* Num Local frames done */
  319. + __le32 local_freed;
  320. +
  321. + /* Num queued to HW */
  322. + __le32 hw_queued;
  323. +
  324. + /* Num PPDU reaped from HW */
  325. + __le32 hw_reaped;
  326. +
  327. + /* Num underruns */
  328. + __le32 underrun;
  329. +
  330. + /* HW Paused. */
  331. + __le32 hw_paused;
  332. +
  333. + /* Num PPDUs cleaned up in TX abort */
  334. + __le32 tx_abort;
  335. +
  336. + /* Num MPDUs requed by SW */
  337. + __le32 mpdus_requed;
  338. +
  339. + /* excessive retries */
  340. + __le32 tx_ko;
  341. +
  342. + /* data hw rate code */
  343. + __le32 data_rc;
  344. +
  345. + /* Scheduler self triggers */
  346. + __le32 self_triggers;
  347. +
  348. + /* frames dropped due to excessive sw retries */
  349. + __le32 sw_retry_failure;
  350. +
  351. + /* illegal rate phy errors */
  352. + __le32 illgl_rate_phy_err;
  353. +
  354. + /* wal pdev continuous xretry */
  355. + __le32 pdev_cont_xretry;
  356. +
  357. + /* wal pdev tx timeouts */
  358. + __le32 pdev_tx_timeout;
  359. +
  360. + /* wal pdev resets */
  361. + __le32 pdev_resets;
  362. +
  363. + /* frames dropped due to non-availability of stateless TIDs */
  364. + __le32 stateless_tid_alloc_failure;
  365. +
  366. + __le32 phy_underrun;
  367. +
  368. + /* MPDU is more than txop limit */
  369. + __le32 txop_ovf;
  370. +
  371. + /* Number of Sequences posted */
  372. + __le32 seq_posted;
  373. +
  374. + /* Number of Sequences failed queueing */
  375. + __le32 seq_failed_queueing;
  376. +
  377. + /* Number of Sequences completed */
  378. + __le32 seq_completed;
  379. +
  380. + /* Number of Sequences restarted */
  381. + __le32 seq_restarted;
  382. +
  383. + /* Number of MU Sequences posted */
  384. + __le32 mu_seq_posted;
  385. +
  386. + /* Num MPDUs flushed by SW, HWPAUSED,SW TXABORT(Reset,channel change) */
  387. + __le32 mpdus_sw_flush;
  388. +
  389. + /* Num MPDUs filtered by HW, all filter condition (TTL expired) */
  390. + __le32 mpdus_hw_filter;
  391. +
  392. + /* Num MPDUs truncated by PDG
  393. + * (TXOP, TBTT, PPDU_duration based on rate, dyn_bw)
  394. + */
  395. + __le32 mpdus_truncated;
  396. +
  397. + /* Num MPDUs that was tried but didn't receive ACK or BA */
  398. + __le32 mpdus_ack_failed;
  399. +
  400. + /* Num MPDUs that was dropped due to expiry. */
  401. + __le32 mpdus_expired;
  402. +} __packed;
  403. +
  404. struct wmi_pdev_stats_rx {
  405. /* Cnts any change in ring routing mid-ppdu */
  406. __le32 mid_ppdu_route_change;
  407. @@ -4039,6 +4144,16 @@ struct wmi_10_2_pdev_stats {
  408. struct wmi_pdev_stats_extra extra;
  409. } __packed;
  410. +struct wmi_10_4_pdev_stats {
  411. + struct wmi_pdev_stats_base base;
  412. + struct wmi_10_4_pdev_stats_tx tx;
  413. + struct wmi_pdev_stats_rx rx;
  414. + __le32 rx_ovfl_errs;
  415. + struct wmi_pdev_stats_mem mem;
  416. + __le32 sram_free_size;
  417. + struct wmi_pdev_stats_extra extra;
  418. +} __packed;
  419. +
  420. /*
  421. * VDEV statistics
  422. * TODO: add all VDEV stats here
  423. @@ -4080,6 +4195,23 @@ struct wmi_10_2_4_peer_stats {
  424. __le32 unknown_value; /* FIXME: what is this word? */
  425. } __packed;
  426. +struct wmi_10_4_peer_stats {
  427. + struct wmi_mac_addr peer_macaddr;
  428. + __le32 peer_rssi;
  429. + __le32 peer_rssi_seq_num;
  430. + __le32 peer_tx_rate;
  431. + __le32 peer_rx_rate;
  432. + __le32 current_per;
  433. + __le32 retries;
  434. + __le32 tx_rate_count;
  435. + __le32 max_4ms_frame_len;
  436. + __le32 total_sub_frames;
  437. + __le32 tx_bytes;
  438. + __le32 num_pkt_loss_overflow[4];
  439. + __le32 num_pkt_loss_excess_retry[4];
  440. + __le32 peer_rssi_changed;
  441. +} __packed;
  442. +
  443. struct wmi_10_2_pdev_ext_stats {
  444. __le32 rx_rssi_comb;
  445. __le32 rx_rssi[4];
  446. @@ -6201,5 +6333,8 @@ void ath10k_wmi_10x_op_fw_stats_fill(str
  447. char *buf);
  448. size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head);
  449. size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head);
  450. +void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
  451. + struct ath10k_fw_stats *fw_stats,
  452. + char *buf);
  453. #endif /* _WMI_H_ */