debugfs_sta.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. /*
  2. * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
  3. * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include "core.h"
  18. #include "wmi-ops.h"
  19. #include "txrx.h"
  20. #include "debug.h"
  21. static void ath10k_rx_stats_update_amsdu_subfrm(struct ath10k *ar,
  22. struct ath10k_sta_tid_stats *stats,
  23. u32 msdu_count)
  24. {
  25. if (msdu_count == 1)
  26. stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_1]++;
  27. else if (msdu_count == 2)
  28. stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_2]++;
  29. else if (msdu_count == 3)
  30. stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_3]++;
  31. else if (msdu_count == 4)
  32. stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_4]++;
  33. else if (msdu_count > 4)
  34. stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MORE]++;
  35. }
  36. static void ath10k_rx_stats_update_ampdu_subfrm(struct ath10k *ar,
  37. struct ath10k_sta_tid_stats *stats,
  38. u32 mpdu_count)
  39. {
  40. if (mpdu_count <= 10)
  41. stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_10]++;
  42. else if (mpdu_count <= 20)
  43. stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_20]++;
  44. else if (mpdu_count <= 30)
  45. stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_30]++;
  46. else if (mpdu_count <= 40)
  47. stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_40]++;
  48. else if (mpdu_count <= 50)
  49. stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_50]++;
  50. else if (mpdu_count <= 60)
  51. stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_60]++;
  52. else if (mpdu_count > 60)
  53. stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MORE]++;
  54. }
  55. void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar, u16 peer_id, u8 tid,
  56. struct htt_rx_indication_mpdu_range *ranges,
  57. int num_ranges)
  58. {
  59. struct ath10k_sta *arsta;
  60. struct ath10k_peer *peer;
  61. int i;
  62. if (tid > IEEE80211_NUM_TIDS || !(ar->sta_tid_stats_mask & BIT(tid)))
  63. return;
  64. rcu_read_lock();
  65. spin_lock_bh(&ar->data_lock);
  66. peer = ath10k_peer_find_by_id(ar, peer_id);
  67. if (!peer)
  68. goto out;
  69. arsta = (struct ath10k_sta *)peer->sta->drv_priv;
  70. for (i = 0; i < num_ranges; i++)
  71. ath10k_rx_stats_update_ampdu_subfrm(ar,
  72. &arsta->tid_stats[tid],
  73. ranges[i].mpdu_count);
  74. out:
  75. spin_unlock_bh(&ar->data_lock);
  76. rcu_read_unlock();
  77. }
  78. void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr,
  79. unsigned long int num_msdus,
  80. enum ath10k_pkt_rx_err err,
  81. unsigned long int unchain_cnt,
  82. unsigned long int drop_cnt,
  83. unsigned long int drop_cnt_filter,
  84. unsigned long int queued_msdus)
  85. {
  86. struct ieee80211_sta *sta;
  87. struct ath10k_sta *arsta;
  88. struct ieee80211_hdr *hdr;
  89. struct ath10k_sta_tid_stats *stats;
  90. u8 tid = IEEE80211_NUM_TIDS;
  91. bool non_data_frm = false;
  92. hdr = (struct ieee80211_hdr *)first_hdr;
  93. if (!ieee80211_is_data(hdr->frame_control))
  94. non_data_frm = true;
  95. if (ieee80211_is_data_qos(hdr->frame_control))
  96. tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
  97. if (!(ar->sta_tid_stats_mask & BIT(tid)) || non_data_frm)
  98. return;
  99. rcu_read_lock();
  100. sta = ieee80211_find_sta_by_ifaddr(ar->hw, hdr->addr2, NULL);
  101. if (!sta)
  102. goto exit;
  103. arsta = (struct ath10k_sta *)sta->drv_priv;
  104. spin_lock_bh(&ar->data_lock);
  105. stats = &arsta->tid_stats[tid];
  106. stats->rx_pkt_from_fw += num_msdus;
  107. stats->rx_pkt_unchained += unchain_cnt;
  108. stats->rx_pkt_drop_chained += drop_cnt;
  109. stats->rx_pkt_drop_filter += drop_cnt_filter;
  110. if (err != ATH10K_PKT_RX_ERR_MAX)
  111. stats->rx_pkt_err[err] += queued_msdus;
  112. stats->rx_pkt_queued_for_mac += queued_msdus;
  113. ath10k_rx_stats_update_amsdu_subfrm(ar, &arsta->tid_stats[tid],
  114. num_msdus);
  115. spin_unlock_bh(&ar->data_lock);
  116. exit:
  117. rcu_read_unlock();
  118. }
  119. static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar,
  120. struct ath10k_fw_stats *stats)
  121. {
  122. struct ath10k_fw_extd_stats_peer *peer;
  123. struct ieee80211_sta *sta;
  124. struct ath10k_sta *arsta;
  125. rcu_read_lock();
  126. list_for_each_entry(peer, &stats->peers_extd, list) {
  127. sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
  128. NULL);
  129. if (!sta)
  130. continue;
  131. arsta = (struct ath10k_sta *)sta->drv_priv;
  132. arsta->rx_duration += (u64)peer->rx_duration;
  133. }
  134. rcu_read_unlock();
  135. }
  136. static void ath10k_sta_update_stats_rx_duration(struct ath10k *ar,
  137. struct ath10k_fw_stats *stats)
  138. {
  139. struct ath10k_fw_stats_peer *peer;
  140. struct ieee80211_sta *sta;
  141. struct ath10k_sta *arsta;
  142. rcu_read_lock();
  143. list_for_each_entry(peer, &stats->peers, list) {
  144. sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
  145. NULL);
  146. if (!sta)
  147. continue;
  148. arsta = (struct ath10k_sta *)sta->drv_priv;
  149. arsta->rx_duration += (u64)peer->rx_duration;
  150. }
  151. rcu_read_unlock();
  152. }
  153. void ath10k_sta_update_rx_duration(struct ath10k *ar,
  154. struct ath10k_fw_stats *stats)
  155. {
  156. if (stats->extended)
  157. ath10k_sta_update_extd_stats_rx_duration(ar, stats);
  158. else
  159. ath10k_sta_update_stats_rx_duration(ar, stats);
  160. }
  161. static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
  162. char __user *user_buf,
  163. size_t count, loff_t *ppos)
  164. {
  165. struct ieee80211_sta *sta = file->private_data;
  166. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  167. struct ath10k *ar = arsta->arvif->ar;
  168. char buf[32];
  169. int len = 0;
  170. mutex_lock(&ar->conf_mutex);
  171. len = scnprintf(buf, sizeof(buf) - len, "aggregation mode: %s\n",
  172. (arsta->aggr_mode == ATH10K_DBG_AGGR_MODE_AUTO) ?
  173. "auto" : "manual");
  174. mutex_unlock(&ar->conf_mutex);
  175. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  176. }
  177. static ssize_t ath10k_dbg_sta_write_aggr_mode(struct file *file,
  178. const char __user *user_buf,
  179. size_t count, loff_t *ppos)
  180. {
  181. struct ieee80211_sta *sta = file->private_data;
  182. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  183. struct ath10k *ar = arsta->arvif->ar;
  184. u32 aggr_mode;
  185. int ret;
  186. if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode))
  187. return -EINVAL;
  188. if (aggr_mode >= ATH10K_DBG_AGGR_MODE_MAX)
  189. return -EINVAL;
  190. mutex_lock(&ar->conf_mutex);
  191. if ((ar->state != ATH10K_STATE_ON) ||
  192. (aggr_mode == arsta->aggr_mode)) {
  193. ret = count;
  194. goto out;
  195. }
  196. ret = ath10k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr);
  197. if (ret) {
  198. ath10k_warn(ar, "failed to clear addba session ret: %d\n", ret);
  199. goto out;
  200. }
  201. arsta->aggr_mode = aggr_mode;
  202. out:
  203. mutex_unlock(&ar->conf_mutex);
  204. return ret;
  205. }
  206. static const struct file_operations fops_aggr_mode = {
  207. .read = ath10k_dbg_sta_read_aggr_mode,
  208. .write = ath10k_dbg_sta_write_aggr_mode,
  209. .open = simple_open,
  210. .owner = THIS_MODULE,
  211. .llseek = default_llseek,
  212. };
  213. static ssize_t ath10k_dbg_sta_write_addba(struct file *file,
  214. const char __user *user_buf,
  215. size_t count, loff_t *ppos)
  216. {
  217. struct ieee80211_sta *sta = file->private_data;
  218. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  219. struct ath10k *ar = arsta->arvif->ar;
  220. u32 tid, buf_size;
  221. int ret;
  222. char buf[64] = {0};
  223. ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
  224. user_buf, count);
  225. if (ret <= 0)
  226. return ret;
  227. ret = sscanf(buf, "%u %u", &tid, &buf_size);
  228. if (ret != 2)
  229. return -EINVAL;
  230. /* Valid TID values are 0 through 15 */
  231. if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
  232. return -EINVAL;
  233. mutex_lock(&ar->conf_mutex);
  234. if ((ar->state != ATH10K_STATE_ON) ||
  235. (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
  236. ret = count;
  237. goto out;
  238. }
  239. ret = ath10k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
  240. tid, buf_size);
  241. if (ret) {
  242. ath10k_warn(ar, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
  243. arsta->arvif->vdev_id, sta->addr, tid, buf_size);
  244. }
  245. ret = count;
  246. out:
  247. mutex_unlock(&ar->conf_mutex);
  248. return ret;
  249. }
  250. static const struct file_operations fops_addba = {
  251. .write = ath10k_dbg_sta_write_addba,
  252. .open = simple_open,
  253. .owner = THIS_MODULE,
  254. .llseek = default_llseek,
  255. };
  256. static ssize_t ath10k_dbg_sta_write_addba_resp(struct file *file,
  257. const char __user *user_buf,
  258. size_t count, loff_t *ppos)
  259. {
  260. struct ieee80211_sta *sta = file->private_data;
  261. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  262. struct ath10k *ar = arsta->arvif->ar;
  263. u32 tid, status;
  264. int ret;
  265. char buf[64] = {0};
  266. ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
  267. user_buf, count);
  268. if (ret <= 0)
  269. return ret;
  270. ret = sscanf(buf, "%u %u", &tid, &status);
  271. if (ret != 2)
  272. return -EINVAL;
  273. /* Valid TID values are 0 through 15 */
  274. if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
  275. return -EINVAL;
  276. mutex_lock(&ar->conf_mutex);
  277. if ((ar->state != ATH10K_STATE_ON) ||
  278. (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
  279. ret = count;
  280. goto out;
  281. }
  282. ret = ath10k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
  283. tid, status);
  284. if (ret) {
  285. ath10k_warn(ar, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
  286. arsta->arvif->vdev_id, sta->addr, tid, status);
  287. }
  288. ret = count;
  289. out:
  290. mutex_unlock(&ar->conf_mutex);
  291. return ret;
  292. }
  293. static const struct file_operations fops_addba_resp = {
  294. .write = ath10k_dbg_sta_write_addba_resp,
  295. .open = simple_open,
  296. .owner = THIS_MODULE,
  297. .llseek = default_llseek,
  298. };
  299. static ssize_t ath10k_dbg_sta_write_delba(struct file *file,
  300. const char __user *user_buf,
  301. size_t count, loff_t *ppos)
  302. {
  303. struct ieee80211_sta *sta = file->private_data;
  304. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  305. struct ath10k *ar = arsta->arvif->ar;
  306. u32 tid, initiator, reason;
  307. int ret;
  308. char buf[64] = {0};
  309. ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
  310. user_buf, count);
  311. if (ret <= 0)
  312. return ret;
  313. ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
  314. if (ret != 3)
  315. return -EINVAL;
  316. /* Valid TID values are 0 through 15 */
  317. if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
  318. return -EINVAL;
  319. mutex_lock(&ar->conf_mutex);
  320. if ((ar->state != ATH10K_STATE_ON) ||
  321. (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
  322. ret = count;
  323. goto out;
  324. }
  325. ret = ath10k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
  326. tid, initiator, reason);
  327. if (ret) {
  328. ath10k_warn(ar, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
  329. arsta->arvif->vdev_id, sta->addr, tid, initiator,
  330. reason);
  331. }
  332. ret = count;
  333. out:
  334. mutex_unlock(&ar->conf_mutex);
  335. return ret;
  336. }
  337. static const struct file_operations fops_delba = {
  338. .write = ath10k_dbg_sta_write_delba,
  339. .open = simple_open,
  340. .owner = THIS_MODULE,
  341. .llseek = default_llseek,
  342. };
  343. static ssize_t ath10k_dbg_sta_read_peer_debug_trigger(struct file *file,
  344. char __user *user_buf,
  345. size_t count,
  346. loff_t *ppos)
  347. {
  348. struct ieee80211_sta *sta = file->private_data;
  349. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  350. struct ath10k *ar = arsta->arvif->ar;
  351. char buf[8];
  352. int len = 0;
  353. mutex_lock(&ar->conf_mutex);
  354. len = scnprintf(buf, sizeof(buf) - len,
  355. "Write 1 to once trigger the debug logs\n");
  356. mutex_unlock(&ar->conf_mutex);
  357. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  358. }
  359. static ssize_t
  360. ath10k_dbg_sta_write_peer_debug_trigger(struct file *file,
  361. const char __user *user_buf,
  362. size_t count, loff_t *ppos)
  363. {
  364. struct ieee80211_sta *sta = file->private_data;
  365. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  366. struct ath10k *ar = arsta->arvif->ar;
  367. u8 peer_debug_trigger;
  368. int ret;
  369. if (kstrtou8_from_user(user_buf, count, 0, &peer_debug_trigger))
  370. return -EINVAL;
  371. if (peer_debug_trigger != 1)
  372. return -EINVAL;
  373. mutex_lock(&ar->conf_mutex);
  374. if (ar->state != ATH10K_STATE_ON) {
  375. ret = -ENETDOWN;
  376. goto out;
  377. }
  378. ret = ath10k_wmi_peer_set_param(ar, arsta->arvif->vdev_id, sta->addr,
  379. WMI_PEER_DEBUG, peer_debug_trigger);
  380. if (ret) {
  381. ath10k_warn(ar, "failed to set param to trigger peer tid logs for station ret: %d\n",
  382. ret);
  383. goto out;
  384. }
  385. out:
  386. mutex_unlock(&ar->conf_mutex);
  387. return count;
  388. }
  389. static const struct file_operations fops_peer_debug_trigger = {
  390. .open = simple_open,
  391. .read = ath10k_dbg_sta_read_peer_debug_trigger,
  392. .write = ath10k_dbg_sta_write_peer_debug_trigger,
  393. .owner = THIS_MODULE,
  394. .llseek = default_llseek,
  395. };
  396. static char *get_err_str(enum ath10k_pkt_rx_err i)
  397. {
  398. switch (i) {
  399. case ATH10K_PKT_RX_ERR_FCS:
  400. return "fcs_err";
  401. case ATH10K_PKT_RX_ERR_TKIP:
  402. return "tkip_err";
  403. case ATH10K_PKT_RX_ERR_CRYPT:
  404. return "crypt_err";
  405. case ATH10K_PKT_RX_ERR_PEER_IDX_INVAL:
  406. return "peer_idx_inval";
  407. case ATH10K_PKT_RX_ERR_MAX:
  408. return "unknown";
  409. }
  410. return "unknown";
  411. }
  412. static char *get_num_ampdu_subfrm_str(enum ath10k_ampdu_subfrm_num i)
  413. {
  414. switch (i) {
  415. case ATH10K_AMPDU_SUBFRM_NUM_10:
  416. return "upto 10";
  417. case ATH10K_AMPDU_SUBFRM_NUM_20:
  418. return "11-20";
  419. case ATH10K_AMPDU_SUBFRM_NUM_30:
  420. return "21-30";
  421. case ATH10K_AMPDU_SUBFRM_NUM_40:
  422. return "31-40";
  423. case ATH10K_AMPDU_SUBFRM_NUM_50:
  424. return "41-50";
  425. case ATH10K_AMPDU_SUBFRM_NUM_60:
  426. return "51-60";
  427. case ATH10K_AMPDU_SUBFRM_NUM_MORE:
  428. return ">60";
  429. case ATH10K_AMPDU_SUBFRM_NUM_MAX:
  430. return "0";
  431. }
  432. return "0";
  433. }
  434. static char *get_num_amsdu_subfrm_str(enum ath10k_amsdu_subfrm_num i)
  435. {
  436. switch (i) {
  437. case ATH10K_AMSDU_SUBFRM_NUM_1:
  438. return "1";
  439. case ATH10K_AMSDU_SUBFRM_NUM_2:
  440. return "2";
  441. case ATH10K_AMSDU_SUBFRM_NUM_3:
  442. return "3";
  443. case ATH10K_AMSDU_SUBFRM_NUM_4:
  444. return "4";
  445. case ATH10K_AMSDU_SUBFRM_NUM_MORE:
  446. return ">4";
  447. case ATH10K_AMSDU_SUBFRM_NUM_MAX:
  448. return "0";
  449. }
  450. return "0";
  451. }
  452. #define PRINT_TID_STATS(_field, _tabs) \
  453. do { \
  454. int k = 0; \
  455. for (j = 0; j <= IEEE80211_NUM_TIDS; j++) { \
  456. if (ar->sta_tid_stats_mask & BIT(j)) { \
  457. len += scnprintf(buf + len, buf_len - len, \
  458. "[%02d] %-10lu ", \
  459. j, stats[j]._field); \
  460. k++; \
  461. if (k % 8 == 0) { \
  462. len += scnprintf(buf + len, \
  463. buf_len - len, "\n"); \
  464. len += scnprintf(buf + len, \
  465. buf_len - len, \
  466. _tabs); \
  467. } \
  468. } \
  469. } \
  470. len += scnprintf(buf + len, buf_len - len, "\n"); \
  471. } while (0)
  472. static ssize_t ath10k_dbg_sta_read_tid_stats(struct file *file,
  473. char __user *user_buf,
  474. size_t count, loff_t *ppos)
  475. {
  476. struct ieee80211_sta *sta = file->private_data;
  477. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  478. struct ath10k *ar = arsta->arvif->ar;
  479. struct ath10k_sta_tid_stats *stats = arsta->tid_stats;
  480. size_t len = 0, buf_len = 1048 * IEEE80211_NUM_TIDS;
  481. char *buf;
  482. int i, j;
  483. ssize_t ret;
  484. buf = kzalloc(buf_len, GFP_KERNEL);
  485. if (!buf)
  486. return -ENOMEM;
  487. mutex_lock(&ar->conf_mutex);
  488. spin_lock_bh(&ar->data_lock);
  489. len += scnprintf(buf + len, buf_len - len,
  490. "\n\t\tDriver Rx pkt stats per tid, ([tid] count)\n");
  491. len += scnprintf(buf + len, buf_len - len,
  492. "\t\t------------------------------------------\n");
  493. len += scnprintf(buf + len, buf_len - len, "MSDUs from FW\t\t\t");
  494. PRINT_TID_STATS(rx_pkt_from_fw, "\t\t\t\t");
  495. len += scnprintf(buf + len, buf_len - len, "MSDUs unchained\t\t\t");
  496. PRINT_TID_STATS(rx_pkt_unchained, "\t\t\t\t");
  497. len += scnprintf(buf + len, buf_len - len,
  498. "MSDUs locally dropped:chained\t");
  499. PRINT_TID_STATS(rx_pkt_drop_chained, "\t\t\t\t");
  500. len += scnprintf(buf + len, buf_len - len,
  501. "MSDUs locally dropped:filtered\t");
  502. PRINT_TID_STATS(rx_pkt_drop_filter, "\t\t\t\t");
  503. len += scnprintf(buf + len, buf_len - len,
  504. "MSDUs queued for mac80211\t");
  505. PRINT_TID_STATS(rx_pkt_queued_for_mac, "\t\t\t\t");
  506. for (i = 0; i < ATH10K_PKT_RX_ERR_MAX; i++) {
  507. len += scnprintf(buf + len, buf_len - len,
  508. "MSDUs with error:%s\t", get_err_str(i));
  509. PRINT_TID_STATS(rx_pkt_err[i], "\t\t\t\t");
  510. }
  511. len += scnprintf(buf + len, buf_len - len, "\n");
  512. for (i = 0; i < ATH10K_AMPDU_SUBFRM_NUM_MAX; i++) {
  513. len += scnprintf(buf + len, buf_len - len,
  514. "A-MPDU num subframes %s\t",
  515. get_num_ampdu_subfrm_str(i));
  516. PRINT_TID_STATS(rx_pkt_ampdu[i], "\t\t\t\t");
  517. }
  518. len += scnprintf(buf + len, buf_len - len, "\n");
  519. for (i = 0; i < ATH10K_AMSDU_SUBFRM_NUM_MAX; i++) {
  520. len += scnprintf(buf + len, buf_len - len,
  521. "A-MSDU num subframes %s\t\t",
  522. get_num_amsdu_subfrm_str(i));
  523. PRINT_TID_STATS(rx_pkt_amsdu[i], "\t\t\t\t");
  524. }
  525. spin_unlock_bh(&ar->data_lock);
  526. ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
  527. kfree(buf);
  528. mutex_unlock(&ar->conf_mutex);
  529. return ret;
  530. }
  531. static const struct file_operations fops_tid_stats_dump = {
  532. .open = simple_open,
  533. .read = ath10k_dbg_sta_read_tid_stats,
  534. .owner = THIS_MODULE,
  535. .llseek = default_llseek,
  536. };
  537. void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  538. struct ieee80211_sta *sta, struct dentry *dir)
  539. {
  540. debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
  541. debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
  542. debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
  543. debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
  544. debugfs_create_file("peer_debug_trigger", 0600, dir, sta,
  545. &fops_peer_debug_trigger);
  546. debugfs_create_file("dump_tid_stats", 0400, dir, sta,
  547. &fops_tid_stats_dump);
  548. }