debugfs_sta.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. // SPDX-License-Identifier: ISC
  2. /*
  3. * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
  4. * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  5. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  6. */
  7. #include "core.h"
  8. #include "wmi-ops.h"
  9. #include "txrx.h"
  10. #include "debug.h"
  11. static void ath10k_rx_stats_update_amsdu_subfrm(struct ath10k *ar,
  12. struct ath10k_sta_tid_stats *stats,
  13. u32 msdu_count)
  14. {
  15. if (msdu_count == 1)
  16. stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_1]++;
  17. else if (msdu_count == 2)
  18. stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_2]++;
  19. else if (msdu_count == 3)
  20. stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_3]++;
  21. else if (msdu_count == 4)
  22. stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_4]++;
  23. else if (msdu_count > 4)
  24. stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MORE]++;
  25. }
  26. static void ath10k_rx_stats_update_ampdu_subfrm(struct ath10k *ar,
  27. struct ath10k_sta_tid_stats *stats,
  28. u32 mpdu_count)
  29. {
  30. if (mpdu_count <= 10)
  31. stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_10]++;
  32. else if (mpdu_count <= 20)
  33. stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_20]++;
  34. else if (mpdu_count <= 30)
  35. stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_30]++;
  36. else if (mpdu_count <= 40)
  37. stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_40]++;
  38. else if (mpdu_count <= 50)
  39. stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_50]++;
  40. else if (mpdu_count <= 60)
  41. stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_60]++;
  42. else if (mpdu_count > 60)
  43. stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MORE]++;
  44. }
  45. void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar, u16 peer_id, u8 tid,
  46. struct htt_rx_indication_mpdu_range *ranges,
  47. int num_ranges)
  48. {
  49. struct ath10k_sta *arsta;
  50. struct ath10k_peer *peer;
  51. int i;
  52. if (tid > IEEE80211_NUM_TIDS || !(ar->sta_tid_stats_mask & BIT(tid)))
  53. return;
  54. rcu_read_lock();
  55. spin_lock_bh(&ar->data_lock);
  56. peer = ath10k_peer_find_by_id(ar, peer_id);
  57. if (!peer || !peer->sta)
  58. goto out;
  59. arsta = (struct ath10k_sta *)peer->sta->drv_priv;
  60. for (i = 0; i < num_ranges; i++)
  61. ath10k_rx_stats_update_ampdu_subfrm(ar,
  62. &arsta->tid_stats[tid],
  63. ranges[i].mpdu_count);
  64. out:
  65. spin_unlock_bh(&ar->data_lock);
  66. rcu_read_unlock();
  67. }
  68. void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr,
  69. unsigned long num_msdus,
  70. enum ath10k_pkt_rx_err err,
  71. unsigned long unchain_cnt,
  72. unsigned long drop_cnt,
  73. unsigned long drop_cnt_filter,
  74. unsigned long queued_msdus)
  75. {
  76. struct ieee80211_sta *sta;
  77. struct ath10k_sta *arsta;
  78. struct ieee80211_hdr *hdr;
  79. struct ath10k_sta_tid_stats *stats;
  80. u8 tid = IEEE80211_NUM_TIDS;
  81. bool non_data_frm = false;
  82. hdr = (struct ieee80211_hdr *)first_hdr;
  83. if (!ieee80211_is_data(hdr->frame_control))
  84. non_data_frm = true;
  85. if (ieee80211_is_data_qos(hdr->frame_control))
  86. tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
  87. if (!(ar->sta_tid_stats_mask & BIT(tid)) || non_data_frm)
  88. return;
  89. rcu_read_lock();
  90. sta = ieee80211_find_sta_by_ifaddr(ar->hw, hdr->addr2, NULL);
  91. if (!sta)
  92. goto exit;
  93. arsta = (struct ath10k_sta *)sta->drv_priv;
  94. spin_lock_bh(&ar->data_lock);
  95. stats = &arsta->tid_stats[tid];
  96. stats->rx_pkt_from_fw += num_msdus;
  97. stats->rx_pkt_unchained += unchain_cnt;
  98. stats->rx_pkt_drop_chained += drop_cnt;
  99. stats->rx_pkt_drop_filter += drop_cnt_filter;
  100. if (err != ATH10K_PKT_RX_ERR_MAX)
  101. stats->rx_pkt_err[err] += queued_msdus;
  102. stats->rx_pkt_queued_for_mac += queued_msdus;
  103. ath10k_rx_stats_update_amsdu_subfrm(ar, &arsta->tid_stats[tid],
  104. num_msdus);
  105. spin_unlock_bh(&ar->data_lock);
  106. exit:
  107. rcu_read_unlock();
  108. }
  109. static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar,
  110. struct ath10k_fw_stats *stats)
  111. {
  112. struct ath10k_fw_extd_stats_peer *peer;
  113. struct ieee80211_sta *sta;
  114. struct ath10k_sta *arsta;
  115. rcu_read_lock();
  116. list_for_each_entry(peer, &stats->peers_extd, list) {
  117. sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
  118. NULL);
  119. if (!sta)
  120. continue;
  121. arsta = (struct ath10k_sta *)sta->drv_priv;
  122. arsta->rx_duration += (u64)peer->rx_duration;
  123. }
  124. rcu_read_unlock();
  125. }
  126. static void ath10k_sta_update_stats_rx_duration(struct ath10k *ar,
  127. struct ath10k_fw_stats *stats)
  128. {
  129. struct ath10k_fw_stats_peer *peer;
  130. struct ieee80211_sta *sta;
  131. struct ath10k_sta *arsta;
  132. rcu_read_lock();
  133. list_for_each_entry(peer, &stats->peers, list) {
  134. sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
  135. NULL);
  136. if (!sta)
  137. continue;
  138. arsta = (struct ath10k_sta *)sta->drv_priv;
  139. arsta->rx_duration += (u64)peer->rx_duration;
  140. }
  141. rcu_read_unlock();
  142. }
  143. void ath10k_sta_update_rx_duration(struct ath10k *ar,
  144. struct ath10k_fw_stats *stats)
  145. {
  146. if (stats->extended)
  147. ath10k_sta_update_extd_stats_rx_duration(ar, stats);
  148. else
  149. ath10k_sta_update_stats_rx_duration(ar, stats);
  150. }
  151. static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
  152. char __user *user_buf,
  153. size_t count, loff_t *ppos)
  154. {
  155. struct ieee80211_sta *sta = file->private_data;
  156. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  157. struct ath10k *ar = arsta->arvif->ar;
  158. char buf[32];
  159. int len = 0;
  160. mutex_lock(&ar->conf_mutex);
  161. len = scnprintf(buf, sizeof(buf) - len, "aggregation mode: %s\n",
  162. (arsta->aggr_mode == ATH10K_DBG_AGGR_MODE_AUTO) ?
  163. "auto" : "manual");
  164. mutex_unlock(&ar->conf_mutex);
  165. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  166. }
  167. static ssize_t ath10k_dbg_sta_write_aggr_mode(struct file *file,
  168. const char __user *user_buf,
  169. size_t count, loff_t *ppos)
  170. {
  171. struct ieee80211_sta *sta = file->private_data;
  172. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  173. struct ath10k *ar = arsta->arvif->ar;
  174. u32 aggr_mode;
  175. int ret;
  176. if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode))
  177. return -EINVAL;
  178. if (aggr_mode >= ATH10K_DBG_AGGR_MODE_MAX)
  179. return -EINVAL;
  180. mutex_lock(&ar->conf_mutex);
  181. if ((ar->state != ATH10K_STATE_ON) ||
  182. (aggr_mode == arsta->aggr_mode)) {
  183. ret = count;
  184. goto out;
  185. }
  186. ret = ath10k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr);
  187. if (ret) {
  188. ath10k_warn(ar, "failed to clear addba session ret: %d\n", ret);
  189. goto out;
  190. }
  191. arsta->aggr_mode = aggr_mode;
  192. out:
  193. mutex_unlock(&ar->conf_mutex);
  194. return ret;
  195. }
  196. static const struct file_operations fops_aggr_mode = {
  197. .read = ath10k_dbg_sta_read_aggr_mode,
  198. .write = ath10k_dbg_sta_write_aggr_mode,
  199. .open = simple_open,
  200. .owner = THIS_MODULE,
  201. .llseek = default_llseek,
  202. };
  203. static ssize_t ath10k_dbg_sta_write_addba(struct file *file,
  204. const char __user *user_buf,
  205. size_t count, loff_t *ppos)
  206. {
  207. struct ieee80211_sta *sta = file->private_data;
  208. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  209. struct ath10k *ar = arsta->arvif->ar;
  210. u32 tid, buf_size;
  211. int ret;
  212. char buf[64] = {0};
  213. ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
  214. user_buf, count);
  215. if (ret <= 0)
  216. return ret;
  217. ret = sscanf(buf, "%u %u", &tid, &buf_size);
  218. if (ret != 2)
  219. return -EINVAL;
  220. /* Valid TID values are 0 through 15 */
  221. if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
  222. return -EINVAL;
  223. mutex_lock(&ar->conf_mutex);
  224. if ((ar->state != ATH10K_STATE_ON) ||
  225. (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
  226. ret = count;
  227. goto out;
  228. }
  229. ret = ath10k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
  230. tid, buf_size);
  231. if (ret) {
  232. ath10k_warn(ar, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
  233. arsta->arvif->vdev_id, sta->addr, tid, buf_size);
  234. }
  235. ret = count;
  236. out:
  237. mutex_unlock(&ar->conf_mutex);
  238. return ret;
  239. }
  240. static const struct file_operations fops_addba = {
  241. .write = ath10k_dbg_sta_write_addba,
  242. .open = simple_open,
  243. .owner = THIS_MODULE,
  244. .llseek = default_llseek,
  245. };
  246. static ssize_t ath10k_dbg_sta_write_addba_resp(struct file *file,
  247. const char __user *user_buf,
  248. size_t count, loff_t *ppos)
  249. {
  250. struct ieee80211_sta *sta = file->private_data;
  251. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  252. struct ath10k *ar = arsta->arvif->ar;
  253. u32 tid, status;
  254. int ret;
  255. char buf[64] = {0};
  256. ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
  257. user_buf, count);
  258. if (ret <= 0)
  259. return ret;
  260. ret = sscanf(buf, "%u %u", &tid, &status);
  261. if (ret != 2)
  262. return -EINVAL;
  263. /* Valid TID values are 0 through 15 */
  264. if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
  265. return -EINVAL;
  266. mutex_lock(&ar->conf_mutex);
  267. if ((ar->state != ATH10K_STATE_ON) ||
  268. (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
  269. ret = count;
  270. goto out;
  271. }
  272. ret = ath10k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
  273. tid, status);
  274. if (ret) {
  275. ath10k_warn(ar, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
  276. arsta->arvif->vdev_id, sta->addr, tid, status);
  277. }
  278. ret = count;
  279. out:
  280. mutex_unlock(&ar->conf_mutex);
  281. return ret;
  282. }
  283. static const struct file_operations fops_addba_resp = {
  284. .write = ath10k_dbg_sta_write_addba_resp,
  285. .open = simple_open,
  286. .owner = THIS_MODULE,
  287. .llseek = default_llseek,
  288. };
  289. static ssize_t ath10k_dbg_sta_write_delba(struct file *file,
  290. const char __user *user_buf,
  291. size_t count, loff_t *ppos)
  292. {
  293. struct ieee80211_sta *sta = file->private_data;
  294. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  295. struct ath10k *ar = arsta->arvif->ar;
  296. u32 tid, initiator, reason;
  297. int ret;
  298. char buf[64] = {0};
  299. ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
  300. user_buf, count);
  301. if (ret <= 0)
  302. return ret;
  303. ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
  304. if (ret != 3)
  305. return -EINVAL;
  306. /* Valid TID values are 0 through 15 */
  307. if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
  308. return -EINVAL;
  309. mutex_lock(&ar->conf_mutex);
  310. if ((ar->state != ATH10K_STATE_ON) ||
  311. (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
  312. ret = count;
  313. goto out;
  314. }
  315. ret = ath10k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
  316. tid, initiator, reason);
  317. if (ret) {
  318. ath10k_warn(ar, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
  319. arsta->arvif->vdev_id, sta->addr, tid, initiator,
  320. reason);
  321. }
  322. ret = count;
  323. out:
  324. mutex_unlock(&ar->conf_mutex);
  325. return ret;
  326. }
  327. static const struct file_operations fops_delba = {
  328. .write = ath10k_dbg_sta_write_delba,
  329. .open = simple_open,
  330. .owner = THIS_MODULE,
  331. .llseek = default_llseek,
  332. };
  333. static ssize_t ath10k_dbg_sta_read_peer_debug_trigger(struct file *file,
  334. char __user *user_buf,
  335. size_t count,
  336. loff_t *ppos)
  337. {
  338. struct ieee80211_sta *sta = file->private_data;
  339. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  340. struct ath10k *ar = arsta->arvif->ar;
  341. char buf[8];
  342. int len = 0;
  343. mutex_lock(&ar->conf_mutex);
  344. len = scnprintf(buf, sizeof(buf) - len,
  345. "Write 1 to once trigger the debug logs\n");
  346. mutex_unlock(&ar->conf_mutex);
  347. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  348. }
  349. static ssize_t
  350. ath10k_dbg_sta_write_peer_debug_trigger(struct file *file,
  351. const char __user *user_buf,
  352. size_t count, loff_t *ppos)
  353. {
  354. struct ieee80211_sta *sta = file->private_data;
  355. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  356. struct ath10k *ar = arsta->arvif->ar;
  357. u8 peer_debug_trigger;
  358. int ret;
  359. if (kstrtou8_from_user(user_buf, count, 0, &peer_debug_trigger))
  360. return -EINVAL;
  361. if (peer_debug_trigger != 1)
  362. return -EINVAL;
  363. mutex_lock(&ar->conf_mutex);
  364. if (ar->state != ATH10K_STATE_ON) {
  365. ret = -ENETDOWN;
  366. goto out;
  367. }
  368. ret = ath10k_wmi_peer_set_param(ar, arsta->arvif->vdev_id, sta->addr,
  369. ar->wmi.peer_param->debug, peer_debug_trigger);
  370. if (ret) {
  371. ath10k_warn(ar, "failed to set param to trigger peer tid logs for station ret: %d\n",
  372. ret);
  373. goto out;
  374. }
  375. out:
  376. mutex_unlock(&ar->conf_mutex);
  377. return ret ?: count;
  378. }
  379. static const struct file_operations fops_peer_debug_trigger = {
  380. .open = simple_open,
  381. .read = ath10k_dbg_sta_read_peer_debug_trigger,
  382. .write = ath10k_dbg_sta_write_peer_debug_trigger,
  383. .owner = THIS_MODULE,
  384. .llseek = default_llseek,
  385. };
  386. static ssize_t ath10k_dbg_sta_read_peer_ps_state(struct file *file,
  387. char __user *user_buf,
  388. size_t count, loff_t *ppos)
  389. {
  390. struct ieee80211_sta *sta = file->private_data;
  391. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  392. struct ath10k *ar = arsta->arvif->ar;
  393. char buf[20];
  394. int len = 0;
  395. spin_lock_bh(&ar->data_lock);
  396. len = scnprintf(buf, sizeof(buf) - len, "%d\n",
  397. arsta->peer_ps_state);
  398. spin_unlock_bh(&ar->data_lock);
  399. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  400. }
  401. static const struct file_operations fops_peer_ps_state = {
  402. .open = simple_open,
  403. .read = ath10k_dbg_sta_read_peer_ps_state,
  404. .owner = THIS_MODULE,
  405. .llseek = default_llseek,
  406. };
  407. static char *get_err_str(enum ath10k_pkt_rx_err i)
  408. {
  409. switch (i) {
  410. case ATH10K_PKT_RX_ERR_FCS:
  411. return "fcs_err";
  412. case ATH10K_PKT_RX_ERR_TKIP:
  413. return "tkip_err";
  414. case ATH10K_PKT_RX_ERR_CRYPT:
  415. return "crypt_err";
  416. case ATH10K_PKT_RX_ERR_PEER_IDX_INVAL:
  417. return "peer_idx_inval";
  418. case ATH10K_PKT_RX_ERR_MAX:
  419. return "unknown";
  420. }
  421. return "unknown";
  422. }
  423. static char *get_num_ampdu_subfrm_str(enum ath10k_ampdu_subfrm_num i)
  424. {
  425. switch (i) {
  426. case ATH10K_AMPDU_SUBFRM_NUM_10:
  427. return "up to 10";
  428. case ATH10K_AMPDU_SUBFRM_NUM_20:
  429. return "11-20";
  430. case ATH10K_AMPDU_SUBFRM_NUM_30:
  431. return "21-30";
  432. case ATH10K_AMPDU_SUBFRM_NUM_40:
  433. return "31-40";
  434. case ATH10K_AMPDU_SUBFRM_NUM_50:
  435. return "41-50";
  436. case ATH10K_AMPDU_SUBFRM_NUM_60:
  437. return "51-60";
  438. case ATH10K_AMPDU_SUBFRM_NUM_MORE:
  439. return ">60";
  440. case ATH10K_AMPDU_SUBFRM_NUM_MAX:
  441. return "0";
  442. }
  443. return "0";
  444. }
  445. static char *get_num_amsdu_subfrm_str(enum ath10k_amsdu_subfrm_num i)
  446. {
  447. switch (i) {
  448. case ATH10K_AMSDU_SUBFRM_NUM_1:
  449. return "1";
  450. case ATH10K_AMSDU_SUBFRM_NUM_2:
  451. return "2";
  452. case ATH10K_AMSDU_SUBFRM_NUM_3:
  453. return "3";
  454. case ATH10K_AMSDU_SUBFRM_NUM_4:
  455. return "4";
  456. case ATH10K_AMSDU_SUBFRM_NUM_MORE:
  457. return ">4";
  458. case ATH10K_AMSDU_SUBFRM_NUM_MAX:
  459. return "0";
  460. }
  461. return "0";
  462. }
  463. #define PRINT_TID_STATS(_field, _tabs) \
  464. do { \
  465. int k = 0; \
  466. for (j = 0; j <= IEEE80211_NUM_TIDS; j++) { \
  467. if (ar->sta_tid_stats_mask & BIT(j)) { \
  468. len += scnprintf(buf + len, buf_len - len, \
  469. "[%02d] %-10lu ", \
  470. j, stats[j]._field); \
  471. k++; \
  472. if (k % 8 == 0) { \
  473. len += scnprintf(buf + len, \
  474. buf_len - len, "\n"); \
  475. len += scnprintf(buf + len, \
  476. buf_len - len, \
  477. _tabs); \
  478. } \
  479. } \
  480. } \
  481. len += scnprintf(buf + len, buf_len - len, "\n"); \
  482. } while (0)
  483. static ssize_t ath10k_dbg_sta_read_tid_stats(struct file *file,
  484. char __user *user_buf,
  485. size_t count, loff_t *ppos)
  486. {
  487. struct ieee80211_sta *sta = file->private_data;
  488. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  489. struct ath10k *ar = arsta->arvif->ar;
  490. struct ath10k_sta_tid_stats *stats = arsta->tid_stats;
  491. size_t len = 0, buf_len = 1048 * IEEE80211_NUM_TIDS;
  492. char *buf;
  493. int i, j;
  494. ssize_t ret;
  495. buf = kzalloc(buf_len, GFP_KERNEL);
  496. if (!buf)
  497. return -ENOMEM;
  498. mutex_lock(&ar->conf_mutex);
  499. spin_lock_bh(&ar->data_lock);
  500. len += scnprintf(buf + len, buf_len - len,
  501. "\n\t\tDriver Rx pkt stats per tid, ([tid] count)\n");
  502. len += scnprintf(buf + len, buf_len - len,
  503. "\t\t------------------------------------------\n");
  504. len += scnprintf(buf + len, buf_len - len, "MSDUs from FW\t\t\t");
  505. PRINT_TID_STATS(rx_pkt_from_fw, "\t\t\t\t");
  506. len += scnprintf(buf + len, buf_len - len, "MSDUs unchained\t\t\t");
  507. PRINT_TID_STATS(rx_pkt_unchained, "\t\t\t\t");
  508. len += scnprintf(buf + len, buf_len - len,
  509. "MSDUs locally dropped:chained\t");
  510. PRINT_TID_STATS(rx_pkt_drop_chained, "\t\t\t\t");
  511. len += scnprintf(buf + len, buf_len - len,
  512. "MSDUs locally dropped:filtered\t");
  513. PRINT_TID_STATS(rx_pkt_drop_filter, "\t\t\t\t");
  514. len += scnprintf(buf + len, buf_len - len,
  515. "MSDUs queued for mac80211\t");
  516. PRINT_TID_STATS(rx_pkt_queued_for_mac, "\t\t\t\t");
  517. for (i = 0; i < ATH10K_PKT_RX_ERR_MAX; i++) {
  518. len += scnprintf(buf + len, buf_len - len,
  519. "MSDUs with error:%s\t", get_err_str(i));
  520. PRINT_TID_STATS(rx_pkt_err[i], "\t\t\t\t");
  521. }
  522. len += scnprintf(buf + len, buf_len - len, "\n");
  523. for (i = 0; i < ATH10K_AMPDU_SUBFRM_NUM_MAX; i++) {
  524. len += scnprintf(buf + len, buf_len - len,
  525. "A-MPDU num subframes %s\t",
  526. get_num_ampdu_subfrm_str(i));
  527. PRINT_TID_STATS(rx_pkt_ampdu[i], "\t\t\t\t");
  528. }
  529. len += scnprintf(buf + len, buf_len - len, "\n");
  530. for (i = 0; i < ATH10K_AMSDU_SUBFRM_NUM_MAX; i++) {
  531. len += scnprintf(buf + len, buf_len - len,
  532. "A-MSDU num subframes %s\t\t",
  533. get_num_amsdu_subfrm_str(i));
  534. PRINT_TID_STATS(rx_pkt_amsdu[i], "\t\t\t\t");
  535. }
  536. spin_unlock_bh(&ar->data_lock);
  537. ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
  538. kfree(buf);
  539. mutex_unlock(&ar->conf_mutex);
  540. return ret;
  541. }
  542. static const struct file_operations fops_tid_stats_dump = {
  543. .open = simple_open,
  544. .read = ath10k_dbg_sta_read_tid_stats,
  545. .owner = THIS_MODULE,
  546. .llseek = default_llseek,
  547. };
  548. static ssize_t ath10k_dbg_sta_dump_tx_stats(struct file *file,
  549. char __user *user_buf,
  550. size_t count, loff_t *ppos)
  551. {
  552. struct ieee80211_sta *sta = file->private_data;
  553. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  554. struct ath10k *ar = arsta->arvif->ar;
  555. struct ath10k_htt_data_stats *stats;
  556. const char *str_name[ATH10K_STATS_TYPE_MAX] = {"succ", "fail",
  557. "retry", "ampdu"};
  558. const char *str[ATH10K_COUNTER_TYPE_MAX] = {"bytes", "packets"};
  559. int len = 0, i, j, k, retval = 0;
  560. const int size = 16 * 4096;
  561. char *buf;
  562. buf = kzalloc(size, GFP_KERNEL);
  563. if (!buf)
  564. return -ENOMEM;
  565. mutex_lock(&ar->conf_mutex);
  566. if (!arsta->tx_stats) {
  567. ath10k_warn(ar, "failed to get tx stats");
  568. mutex_unlock(&ar->conf_mutex);
  569. kfree(buf);
  570. return 0;
  571. }
  572. spin_lock_bh(&ar->data_lock);
  573. for (k = 0; k < ATH10K_STATS_TYPE_MAX; k++) {
  574. for (j = 0; j < ATH10K_COUNTER_TYPE_MAX; j++) {
  575. stats = &arsta->tx_stats->stats[k];
  576. len += scnprintf(buf + len, size - len, "%s_%s\n",
  577. str_name[k],
  578. str[j]);
  579. len += scnprintf(buf + len, size - len,
  580. " VHT MCS %s\n",
  581. str[j]);
  582. for (i = 0; i < ATH10K_VHT_MCS_NUM; i++)
  583. len += scnprintf(buf + len, size - len,
  584. " %llu ",
  585. stats->vht[j][i]);
  586. len += scnprintf(buf + len, size - len, "\n");
  587. len += scnprintf(buf + len, size - len, " HT MCS %s\n",
  588. str[j]);
  589. for (i = 0; i < ATH10K_HT_MCS_NUM; i++)
  590. len += scnprintf(buf + len, size - len,
  591. " %llu ", stats->ht[j][i]);
  592. len += scnprintf(buf + len, size - len, "\n");
  593. len += scnprintf(buf + len, size - len,
  594. " BW %s (20,5,10,40,80,160 MHz)\n", str[j]);
  595. len += scnprintf(buf + len, size - len,
  596. " %llu %llu %llu %llu %llu %llu\n",
  597. stats->bw[j][0], stats->bw[j][1],
  598. stats->bw[j][2], stats->bw[j][3],
  599. stats->bw[j][4], stats->bw[j][5]);
  600. len += scnprintf(buf + len, size - len,
  601. " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
  602. len += scnprintf(buf + len, size - len,
  603. " %llu %llu %llu %llu\n",
  604. stats->nss[j][0], stats->nss[j][1],
  605. stats->nss[j][2], stats->nss[j][3]);
  606. len += scnprintf(buf + len, size - len,
  607. " GI %s (LGI,SGI)\n",
  608. str[j]);
  609. len += scnprintf(buf + len, size - len, " %llu %llu\n",
  610. stats->gi[j][0], stats->gi[j][1]);
  611. len += scnprintf(buf + len, size - len,
  612. " legacy rate %s (1,2 ... Mbps)\n ",
  613. str[j]);
  614. for (i = 0; i < ATH10K_LEGACY_NUM; i++)
  615. len += scnprintf(buf + len, size - len, "%llu ",
  616. stats->legacy[j][i]);
  617. len += scnprintf(buf + len, size - len, "\n");
  618. len += scnprintf(buf + len, size - len,
  619. " Rate table %s (1,2 ... Mbps)\n ",
  620. str[j]);
  621. for (i = 0; i < ATH10K_RATE_TABLE_NUM; i++) {
  622. len += scnprintf(buf + len, size - len, "%llu ",
  623. stats->rate_table[j][i]);
  624. if (!((i + 1) % 8))
  625. len +=
  626. scnprintf(buf + len, size - len, "\n ");
  627. }
  628. }
  629. }
  630. len += scnprintf(buf + len, size - len,
  631. "\nTX duration\n %llu usecs\n",
  632. arsta->tx_stats->tx_duration);
  633. len += scnprintf(buf + len, size - len,
  634. "BA fails\n %llu\n", arsta->tx_stats->ba_fails);
  635. len += scnprintf(buf + len, size - len,
  636. "ack fails\n %llu\n", arsta->tx_stats->ack_fails);
  637. spin_unlock_bh(&ar->data_lock);
  638. if (len > size)
  639. len = size;
  640. retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
  641. kfree(buf);
  642. mutex_unlock(&ar->conf_mutex);
  643. return retval;
  644. }
  645. static const struct file_operations fops_tx_stats = {
  646. .read = ath10k_dbg_sta_dump_tx_stats,
  647. .open = simple_open,
  648. .owner = THIS_MODULE,
  649. .llseek = default_llseek,
  650. };
  651. void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  652. struct ieee80211_sta *sta, struct dentry *dir)
  653. {
  654. struct ath10k *ar = hw->priv;
  655. debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
  656. debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
  657. debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
  658. debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
  659. debugfs_create_file("peer_debug_trigger", 0600, dir, sta,
  660. &fops_peer_debug_trigger);
  661. debugfs_create_file("dump_tid_stats", 0400, dir, sta,
  662. &fops_tid_stats_dump);
  663. if (ath10k_peer_stats_enabled(ar) &&
  664. ath10k_debug_is_extd_tx_stats_enabled(ar))
  665. debugfs_create_file("tx_stats", 0400, dir, sta,
  666. &fops_tx_stats);
  667. debugfs_create_file("peer_ps_state", 0400, dir, sta,
  668. &fops_peer_ps_state);
  669. }