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];
  223. simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
  224. /* make sure that buf is null terminated */
  225. buf[sizeof(buf) - 1] = '\0';
  226. ret = sscanf(buf, "%u %u", &tid, &buf_size);
  227. if (ret != 2)
  228. return -EINVAL;
  229. /* Valid TID values are 0 through 15 */
  230. if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
  231. return -EINVAL;
  232. mutex_lock(&ar->conf_mutex);
  233. if ((ar->state != ATH10K_STATE_ON) ||
  234. (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
  235. ret = count;
  236. goto out;
  237. }
  238. ret = ath10k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
  239. tid, buf_size);
  240. if (ret) {
  241. ath10k_warn(ar, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
  242. arsta->arvif->vdev_id, sta->addr, tid, buf_size);
  243. }
  244. ret = count;
  245. out:
  246. mutex_unlock(&ar->conf_mutex);
  247. return ret;
  248. }
  249. static const struct file_operations fops_addba = {
  250. .write = ath10k_dbg_sta_write_addba,
  251. .open = simple_open,
  252. .owner = THIS_MODULE,
  253. .llseek = default_llseek,
  254. };
  255. static ssize_t ath10k_dbg_sta_write_addba_resp(struct file *file,
  256. const char __user *user_buf,
  257. size_t count, loff_t *ppos)
  258. {
  259. struct ieee80211_sta *sta = file->private_data;
  260. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  261. struct ath10k *ar = arsta->arvif->ar;
  262. u32 tid, status;
  263. int ret;
  264. char buf[64];
  265. simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
  266. /* make sure that buf is null terminated */
  267. buf[sizeof(buf) - 1] = '\0';
  268. ret = sscanf(buf, "%u %u", &tid, &status);
  269. if (ret != 2)
  270. return -EINVAL;
  271. /* Valid TID values are 0 through 15 */
  272. if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
  273. return -EINVAL;
  274. mutex_lock(&ar->conf_mutex);
  275. if ((ar->state != ATH10K_STATE_ON) ||
  276. (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
  277. ret = count;
  278. goto out;
  279. }
  280. ret = ath10k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
  281. tid, status);
  282. if (ret) {
  283. ath10k_warn(ar, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
  284. arsta->arvif->vdev_id, sta->addr, tid, status);
  285. }
  286. ret = count;
  287. out:
  288. mutex_unlock(&ar->conf_mutex);
  289. return ret;
  290. }
  291. static const struct file_operations fops_addba_resp = {
  292. .write = ath10k_dbg_sta_write_addba_resp,
  293. .open = simple_open,
  294. .owner = THIS_MODULE,
  295. .llseek = default_llseek,
  296. };
  297. static ssize_t ath10k_dbg_sta_write_delba(struct file *file,
  298. const char __user *user_buf,
  299. size_t count, loff_t *ppos)
  300. {
  301. struct ieee80211_sta *sta = file->private_data;
  302. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  303. struct ath10k *ar = arsta->arvif->ar;
  304. u32 tid, initiator, reason;
  305. int ret;
  306. char buf[64];
  307. simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
  308. /* make sure that buf is null terminated */
  309. buf[sizeof(buf) - 1] = '\0';
  310. ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
  311. if (ret != 3)
  312. return -EINVAL;
  313. /* Valid TID values are 0 through 15 */
  314. if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
  315. return -EINVAL;
  316. mutex_lock(&ar->conf_mutex);
  317. if ((ar->state != ATH10K_STATE_ON) ||
  318. (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
  319. ret = count;
  320. goto out;
  321. }
  322. ret = ath10k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
  323. tid, initiator, reason);
  324. if (ret) {
  325. ath10k_warn(ar, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
  326. arsta->arvif->vdev_id, sta->addr, tid, initiator,
  327. reason);
  328. }
  329. ret = count;
  330. out:
  331. mutex_unlock(&ar->conf_mutex);
  332. return ret;
  333. }
  334. static const struct file_operations fops_delba = {
  335. .write = ath10k_dbg_sta_write_delba,
  336. .open = simple_open,
  337. .owner = THIS_MODULE,
  338. .llseek = default_llseek,
  339. };
  340. static ssize_t ath10k_dbg_sta_read_peer_debug_trigger(struct file *file,
  341. char __user *user_buf,
  342. size_t count,
  343. loff_t *ppos)
  344. {
  345. struct ieee80211_sta *sta = file->private_data;
  346. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  347. struct ath10k *ar = arsta->arvif->ar;
  348. char buf[8];
  349. int len = 0;
  350. mutex_lock(&ar->conf_mutex);
  351. len = scnprintf(buf, sizeof(buf) - len,
  352. "Write 1 to once trigger the debug logs\n");
  353. mutex_unlock(&ar->conf_mutex);
  354. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  355. }
  356. static ssize_t
  357. ath10k_dbg_sta_write_peer_debug_trigger(struct file *file,
  358. const char __user *user_buf,
  359. size_t count, loff_t *ppos)
  360. {
  361. struct ieee80211_sta *sta = file->private_data;
  362. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  363. struct ath10k *ar = arsta->arvif->ar;
  364. u8 peer_debug_trigger;
  365. int ret;
  366. if (kstrtou8_from_user(user_buf, count, 0, &peer_debug_trigger))
  367. return -EINVAL;
  368. if (peer_debug_trigger != 1)
  369. return -EINVAL;
  370. mutex_lock(&ar->conf_mutex);
  371. if (ar->state != ATH10K_STATE_ON) {
  372. ret = -ENETDOWN;
  373. goto out;
  374. }
  375. ret = ath10k_wmi_peer_set_param(ar, arsta->arvif->vdev_id, sta->addr,
  376. WMI_PEER_DEBUG, peer_debug_trigger);
  377. if (ret) {
  378. ath10k_warn(ar, "failed to set param to trigger peer tid logs for station ret: %d\n",
  379. ret);
  380. goto out;
  381. }
  382. out:
  383. mutex_unlock(&ar->conf_mutex);
  384. return count;
  385. }
  386. static const struct file_operations fops_peer_debug_trigger = {
  387. .open = simple_open,
  388. .read = ath10k_dbg_sta_read_peer_debug_trigger,
  389. .write = ath10k_dbg_sta_write_peer_debug_trigger,
  390. .owner = THIS_MODULE,
  391. .llseek = default_llseek,
  392. };
  393. static char *get_err_str(enum ath10k_pkt_rx_err i)
  394. {
  395. switch (i) {
  396. case ATH10K_PKT_RX_ERR_FCS:
  397. return "fcs_err";
  398. case ATH10K_PKT_RX_ERR_TKIP:
  399. return "tkip_err";
  400. case ATH10K_PKT_RX_ERR_CRYPT:
  401. return "crypt_err";
  402. case ATH10K_PKT_RX_ERR_PEER_IDX_INVAL:
  403. return "peer_idx_inval";
  404. case ATH10K_PKT_RX_ERR_MAX:
  405. return "unknown";
  406. }
  407. return "unknown";
  408. }
  409. static char *get_num_ampdu_subfrm_str(enum ath10k_ampdu_subfrm_num i)
  410. {
  411. switch (i) {
  412. case ATH10K_AMPDU_SUBFRM_NUM_10:
  413. return "upto 10";
  414. case ATH10K_AMPDU_SUBFRM_NUM_20:
  415. return "11-20";
  416. case ATH10K_AMPDU_SUBFRM_NUM_30:
  417. return "21-30";
  418. case ATH10K_AMPDU_SUBFRM_NUM_40:
  419. return "31-40";
  420. case ATH10K_AMPDU_SUBFRM_NUM_50:
  421. return "41-50";
  422. case ATH10K_AMPDU_SUBFRM_NUM_60:
  423. return "51-60";
  424. case ATH10K_AMPDU_SUBFRM_NUM_MORE:
  425. return ">60";
  426. case ATH10K_AMPDU_SUBFRM_NUM_MAX:
  427. return "0";
  428. }
  429. return "0";
  430. }
  431. static char *get_num_amsdu_subfrm_str(enum ath10k_amsdu_subfrm_num i)
  432. {
  433. switch (i) {
  434. case ATH10K_AMSDU_SUBFRM_NUM_1:
  435. return "1";
  436. case ATH10K_AMSDU_SUBFRM_NUM_2:
  437. return "2";
  438. case ATH10K_AMSDU_SUBFRM_NUM_3:
  439. return "3";
  440. case ATH10K_AMSDU_SUBFRM_NUM_4:
  441. return "4";
  442. case ATH10K_AMSDU_SUBFRM_NUM_MORE:
  443. return ">4";
  444. case ATH10K_AMSDU_SUBFRM_NUM_MAX:
  445. return "0";
  446. }
  447. return "0";
  448. }
  449. #define PRINT_TID_STATS(_field, _tabs) \
  450. do { \
  451. int k = 0; \
  452. for (j = 0; j <= IEEE80211_NUM_TIDS; j++) { \
  453. if (ar->sta_tid_stats_mask & BIT(j)) { \
  454. len += scnprintf(buf + len, buf_len - len, \
  455. "[%02d] %-10lu ", \
  456. j, stats[j]._field); \
  457. k++; \
  458. if (k % 8 == 0) { \
  459. len += scnprintf(buf + len, \
  460. buf_len - len, "\n"); \
  461. len += scnprintf(buf + len, \
  462. buf_len - len, \
  463. _tabs); \
  464. } \
  465. } \
  466. } \
  467. len += scnprintf(buf + len, buf_len - len, "\n"); \
  468. } while (0)
  469. static ssize_t ath10k_dbg_sta_read_tid_stats(struct file *file,
  470. char __user *user_buf,
  471. size_t count, loff_t *ppos)
  472. {
  473. struct ieee80211_sta *sta = file->private_data;
  474. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  475. struct ath10k *ar = arsta->arvif->ar;
  476. struct ath10k_sta_tid_stats *stats = arsta->tid_stats;
  477. size_t len = 0, buf_len = 1048 * IEEE80211_NUM_TIDS;
  478. char *buf;
  479. int i, j;
  480. ssize_t ret;
  481. buf = kzalloc(buf_len, GFP_KERNEL);
  482. if (!buf)
  483. return -ENOMEM;
  484. mutex_lock(&ar->conf_mutex);
  485. spin_lock_bh(&ar->data_lock);
  486. len += scnprintf(buf + len, buf_len - len,
  487. "\n\t\tDriver Rx pkt stats per tid, ([tid] count)\n");
  488. len += scnprintf(buf + len, buf_len - len,
  489. "\t\t------------------------------------------\n");
  490. len += scnprintf(buf + len, buf_len - len, "MSDUs from FW\t\t\t");
  491. PRINT_TID_STATS(rx_pkt_from_fw, "\t\t\t\t");
  492. len += scnprintf(buf + len, buf_len - len, "MSDUs unchained\t\t\t");
  493. PRINT_TID_STATS(rx_pkt_unchained, "\t\t\t\t");
  494. len += scnprintf(buf + len, buf_len - len,
  495. "MSDUs locally dropped:chained\t");
  496. PRINT_TID_STATS(rx_pkt_drop_chained, "\t\t\t\t");
  497. len += scnprintf(buf + len, buf_len - len,
  498. "MSDUs locally dropped:filtered\t");
  499. PRINT_TID_STATS(rx_pkt_drop_filter, "\t\t\t\t");
  500. len += scnprintf(buf + len, buf_len - len,
  501. "MSDUs queued for mac80211\t");
  502. PRINT_TID_STATS(rx_pkt_queued_for_mac, "\t\t\t\t");
  503. for (i = 0; i < ATH10K_PKT_RX_ERR_MAX; i++) {
  504. len += scnprintf(buf + len, buf_len - len,
  505. "MSDUs with error:%s\t", get_err_str(i));
  506. PRINT_TID_STATS(rx_pkt_err[i], "\t\t\t\t");
  507. }
  508. len += scnprintf(buf + len, buf_len - len, "\n");
  509. for (i = 0; i < ATH10K_AMPDU_SUBFRM_NUM_MAX; i++) {
  510. len += scnprintf(buf + len, buf_len - len,
  511. "A-MPDU num subframes %s\t",
  512. get_num_ampdu_subfrm_str(i));
  513. PRINT_TID_STATS(rx_pkt_ampdu[i], "\t\t\t\t");
  514. }
  515. len += scnprintf(buf + len, buf_len - len, "\n");
  516. for (i = 0; i < ATH10K_AMSDU_SUBFRM_NUM_MAX; i++) {
  517. len += scnprintf(buf + len, buf_len - len,
  518. "A-MSDU num subframes %s\t\t",
  519. get_num_amsdu_subfrm_str(i));
  520. PRINT_TID_STATS(rx_pkt_amsdu[i], "\t\t\t\t");
  521. }
  522. spin_unlock_bh(&ar->data_lock);
  523. ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
  524. kfree(buf);
  525. mutex_unlock(&ar->conf_mutex);
  526. return ret;
  527. }
  528. static const struct file_operations fops_tid_stats_dump = {
  529. .open = simple_open,
  530. .read = ath10k_dbg_sta_read_tid_stats,
  531. .owner = THIS_MODULE,
  532. .llseek = default_llseek,
  533. };
  534. void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  535. struct ieee80211_sta *sta, struct dentry *dir)
  536. {
  537. debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
  538. debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
  539. debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
  540. debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
  541. debugfs_create_file("peer_debug_trigger", 0600, dir, sta,
  542. &fops_peer_debug_trigger);
  543. debugfs_create_file("dump_tid_stats", 0400, dir, sta,
  544. &fops_tid_stats_dump);
  545. }