debugfs_sta.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. // SPDX-License-Identifier: BSD-3-Clause-Clear
  2. /*
  3. * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include <linux/vmalloc.h>
  7. #include "debugfs_sta.h"
  8. #include "core.h"
  9. #include "peer.h"
  10. #include "debug.h"
  11. #include "dp_tx.h"
  12. #include "debugfs_htt_stats.h"
  13. void ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta *arsta,
  14. struct ath11k_per_peer_tx_stats *peer_stats,
  15. u8 legacy_rate_idx)
  16. {
  17. struct rate_info *txrate = &arsta->txrate;
  18. struct ath11k_htt_tx_stats *tx_stats;
  19. int gi, mcs, bw, nss;
  20. if (!arsta->tx_stats)
  21. return;
  22. tx_stats = arsta->tx_stats;
  23. gi = FIELD_GET(RATE_INFO_FLAGS_SHORT_GI, arsta->txrate.flags);
  24. mcs = txrate->mcs;
  25. bw = ath11k_mac_mac80211_bw_to_ath11k_bw(txrate->bw);
  26. nss = txrate->nss - 1;
  27. #define STATS_OP_FMT(name) tx_stats->stats[ATH11K_STATS_TYPE_##name]
  28. if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) {
  29. STATS_OP_FMT(SUCC).he[0][mcs] += peer_stats->succ_bytes;
  30. STATS_OP_FMT(SUCC).he[1][mcs] += peer_stats->succ_pkts;
  31. STATS_OP_FMT(FAIL).he[0][mcs] += peer_stats->failed_bytes;
  32. STATS_OP_FMT(FAIL).he[1][mcs] += peer_stats->failed_pkts;
  33. STATS_OP_FMT(RETRY).he[0][mcs] += peer_stats->retry_bytes;
  34. STATS_OP_FMT(RETRY).he[1][mcs] += peer_stats->retry_pkts;
  35. } else if (txrate->flags & RATE_INFO_FLAGS_VHT_MCS) {
  36. STATS_OP_FMT(SUCC).vht[0][mcs] += peer_stats->succ_bytes;
  37. STATS_OP_FMT(SUCC).vht[1][mcs] += peer_stats->succ_pkts;
  38. STATS_OP_FMT(FAIL).vht[0][mcs] += peer_stats->failed_bytes;
  39. STATS_OP_FMT(FAIL).vht[1][mcs] += peer_stats->failed_pkts;
  40. STATS_OP_FMT(RETRY).vht[0][mcs] += peer_stats->retry_bytes;
  41. STATS_OP_FMT(RETRY).vht[1][mcs] += peer_stats->retry_pkts;
  42. } else if (txrate->flags & RATE_INFO_FLAGS_MCS) {
  43. STATS_OP_FMT(SUCC).ht[0][mcs] += peer_stats->succ_bytes;
  44. STATS_OP_FMT(SUCC).ht[1][mcs] += peer_stats->succ_pkts;
  45. STATS_OP_FMT(FAIL).ht[0][mcs] += peer_stats->failed_bytes;
  46. STATS_OP_FMT(FAIL).ht[1][mcs] += peer_stats->failed_pkts;
  47. STATS_OP_FMT(RETRY).ht[0][mcs] += peer_stats->retry_bytes;
  48. STATS_OP_FMT(RETRY).ht[1][mcs] += peer_stats->retry_pkts;
  49. } else {
  50. mcs = legacy_rate_idx;
  51. STATS_OP_FMT(SUCC).legacy[0][mcs] += peer_stats->succ_bytes;
  52. STATS_OP_FMT(SUCC).legacy[1][mcs] += peer_stats->succ_pkts;
  53. STATS_OP_FMT(FAIL).legacy[0][mcs] += peer_stats->failed_bytes;
  54. STATS_OP_FMT(FAIL).legacy[1][mcs] += peer_stats->failed_pkts;
  55. STATS_OP_FMT(RETRY).legacy[0][mcs] += peer_stats->retry_bytes;
  56. STATS_OP_FMT(RETRY).legacy[1][mcs] += peer_stats->retry_pkts;
  57. }
  58. if (peer_stats->is_ampdu) {
  59. tx_stats->ba_fails += peer_stats->ba_fails;
  60. if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) {
  61. STATS_OP_FMT(AMPDU).he[0][mcs] +=
  62. peer_stats->succ_bytes + peer_stats->retry_bytes;
  63. STATS_OP_FMT(AMPDU).he[1][mcs] +=
  64. peer_stats->succ_pkts + peer_stats->retry_pkts;
  65. } else if (txrate->flags & RATE_INFO_FLAGS_MCS) {
  66. STATS_OP_FMT(AMPDU).ht[0][mcs] +=
  67. peer_stats->succ_bytes + peer_stats->retry_bytes;
  68. STATS_OP_FMT(AMPDU).ht[1][mcs] +=
  69. peer_stats->succ_pkts + peer_stats->retry_pkts;
  70. } else {
  71. STATS_OP_FMT(AMPDU).vht[0][mcs] +=
  72. peer_stats->succ_bytes + peer_stats->retry_bytes;
  73. STATS_OP_FMT(AMPDU).vht[1][mcs] +=
  74. peer_stats->succ_pkts + peer_stats->retry_pkts;
  75. }
  76. STATS_OP_FMT(AMPDU).bw[0][bw] +=
  77. peer_stats->succ_bytes + peer_stats->retry_bytes;
  78. STATS_OP_FMT(AMPDU).nss[0][nss] +=
  79. peer_stats->succ_bytes + peer_stats->retry_bytes;
  80. STATS_OP_FMT(AMPDU).gi[0][gi] +=
  81. peer_stats->succ_bytes + peer_stats->retry_bytes;
  82. STATS_OP_FMT(AMPDU).bw[1][bw] +=
  83. peer_stats->succ_pkts + peer_stats->retry_pkts;
  84. STATS_OP_FMT(AMPDU).nss[1][nss] +=
  85. peer_stats->succ_pkts + peer_stats->retry_pkts;
  86. STATS_OP_FMT(AMPDU).gi[1][gi] +=
  87. peer_stats->succ_pkts + peer_stats->retry_pkts;
  88. } else {
  89. tx_stats->ack_fails += peer_stats->ba_fails;
  90. }
  91. STATS_OP_FMT(SUCC).bw[0][bw] += peer_stats->succ_bytes;
  92. STATS_OP_FMT(SUCC).nss[0][nss] += peer_stats->succ_bytes;
  93. STATS_OP_FMT(SUCC).gi[0][gi] += peer_stats->succ_bytes;
  94. STATS_OP_FMT(SUCC).bw[1][bw] += peer_stats->succ_pkts;
  95. STATS_OP_FMT(SUCC).nss[1][nss] += peer_stats->succ_pkts;
  96. STATS_OP_FMT(SUCC).gi[1][gi] += peer_stats->succ_pkts;
  97. STATS_OP_FMT(FAIL).bw[0][bw] += peer_stats->failed_bytes;
  98. STATS_OP_FMT(FAIL).nss[0][nss] += peer_stats->failed_bytes;
  99. STATS_OP_FMT(FAIL).gi[0][gi] += peer_stats->failed_bytes;
  100. STATS_OP_FMT(FAIL).bw[1][bw] += peer_stats->failed_pkts;
  101. STATS_OP_FMT(FAIL).nss[1][nss] += peer_stats->failed_pkts;
  102. STATS_OP_FMT(FAIL).gi[1][gi] += peer_stats->failed_pkts;
  103. STATS_OP_FMT(RETRY).bw[0][bw] += peer_stats->retry_bytes;
  104. STATS_OP_FMT(RETRY).nss[0][nss] += peer_stats->retry_bytes;
  105. STATS_OP_FMT(RETRY).gi[0][gi] += peer_stats->retry_bytes;
  106. STATS_OP_FMT(RETRY).bw[1][bw] += peer_stats->retry_pkts;
  107. STATS_OP_FMT(RETRY).nss[1][nss] += peer_stats->retry_pkts;
  108. STATS_OP_FMT(RETRY).gi[1][gi] += peer_stats->retry_pkts;
  109. tx_stats->tx_duration += peer_stats->duration;
  110. }
  111. void ath11k_debugfs_sta_update_txcompl(struct ath11k *ar,
  112. struct hal_tx_status *ts)
  113. {
  114. ath11k_dp_tx_update_txcompl(ar, ts);
  115. }
  116. static ssize_t ath11k_dbg_sta_dump_tx_stats(struct file *file,
  117. char __user *user_buf,
  118. size_t count, loff_t *ppos)
  119. {
  120. struct ieee80211_sta *sta = file->private_data;
  121. struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  122. struct ath11k *ar = arsta->arvif->ar;
  123. struct ath11k_htt_data_stats *stats;
  124. static const char *str_name[ATH11K_STATS_TYPE_MAX] = {"succ", "fail",
  125. "retry", "ampdu"};
  126. static const char *str[ATH11K_COUNTER_TYPE_MAX] = {"bytes", "packets"};
  127. int len = 0, i, j, k, retval = 0;
  128. const int size = 2 * 4096;
  129. char *buf;
  130. if (!arsta->tx_stats)
  131. return -ENOENT;
  132. buf = kzalloc(size, GFP_KERNEL);
  133. if (!buf)
  134. return -ENOMEM;
  135. mutex_lock(&ar->conf_mutex);
  136. spin_lock_bh(&ar->data_lock);
  137. for (k = 0; k < ATH11K_STATS_TYPE_MAX; k++) {
  138. for (j = 0; j < ATH11K_COUNTER_TYPE_MAX; j++) {
  139. stats = &arsta->tx_stats->stats[k];
  140. len += scnprintf(buf + len, size - len, "%s_%s\n",
  141. str_name[k],
  142. str[j]);
  143. len += scnprintf(buf + len, size - len,
  144. " HE MCS %s\n",
  145. str[j]);
  146. for (i = 0; i < ATH11K_HE_MCS_NUM; i++)
  147. len += scnprintf(buf + len, size - len,
  148. " %llu ",
  149. stats->he[j][i]);
  150. len += scnprintf(buf + len, size - len, "\n");
  151. len += scnprintf(buf + len, size - len,
  152. " VHT MCS %s\n",
  153. str[j]);
  154. for (i = 0; i < ATH11K_VHT_MCS_NUM; i++)
  155. len += scnprintf(buf + len, size - len,
  156. " %llu ",
  157. stats->vht[j][i]);
  158. len += scnprintf(buf + len, size - len, "\n");
  159. len += scnprintf(buf + len, size - len, " HT MCS %s\n",
  160. str[j]);
  161. for (i = 0; i < ATH11K_HT_MCS_NUM; i++)
  162. len += scnprintf(buf + len, size - len,
  163. " %llu ", stats->ht[j][i]);
  164. len += scnprintf(buf + len, size - len, "\n");
  165. len += scnprintf(buf + len, size - len,
  166. " BW %s (20,40,80,160 MHz)\n", str[j]);
  167. len += scnprintf(buf + len, size - len,
  168. " %llu %llu %llu %llu\n",
  169. stats->bw[j][0], stats->bw[j][1],
  170. stats->bw[j][2], stats->bw[j][3]);
  171. len += scnprintf(buf + len, size - len,
  172. " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
  173. len += scnprintf(buf + len, size - len,
  174. " %llu %llu %llu %llu\n",
  175. stats->nss[j][0], stats->nss[j][1],
  176. stats->nss[j][2], stats->nss[j][3]);
  177. len += scnprintf(buf + len, size - len,
  178. " GI %s (0.4us,0.8us,1.6us,3.2us)\n",
  179. str[j]);
  180. len += scnprintf(buf + len, size - len,
  181. " %llu %llu %llu %llu\n",
  182. stats->gi[j][0], stats->gi[j][1],
  183. stats->gi[j][2], stats->gi[j][3]);
  184. len += scnprintf(buf + len, size - len,
  185. " legacy rate %s (1,2 ... Mbps)\n ",
  186. str[j]);
  187. for (i = 0; i < ATH11K_LEGACY_NUM; i++)
  188. len += scnprintf(buf + len, size - len, "%llu ",
  189. stats->legacy[j][i]);
  190. len += scnprintf(buf + len, size - len, "\n");
  191. }
  192. }
  193. len += scnprintf(buf + len, size - len,
  194. "\nTX duration\n %llu usecs\n",
  195. arsta->tx_stats->tx_duration);
  196. len += scnprintf(buf + len, size - len,
  197. "BA fails\n %llu\n", arsta->tx_stats->ba_fails);
  198. len += scnprintf(buf + len, size - len,
  199. "ack fails\n %llu\n", arsta->tx_stats->ack_fails);
  200. spin_unlock_bh(&ar->data_lock);
  201. if (len > size)
  202. len = size;
  203. retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
  204. kfree(buf);
  205. mutex_unlock(&ar->conf_mutex);
  206. return retval;
  207. }
  208. static const struct file_operations fops_tx_stats = {
  209. .read = ath11k_dbg_sta_dump_tx_stats,
  210. .open = simple_open,
  211. .owner = THIS_MODULE,
  212. .llseek = default_llseek,
  213. };
  214. static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file,
  215. char __user *user_buf,
  216. size_t count, loff_t *ppos)
  217. {
  218. struct ieee80211_sta *sta = file->private_data;
  219. struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  220. struct ath11k *ar = arsta->arvif->ar;
  221. struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats;
  222. int len = 0, i, retval = 0;
  223. const int size = 4096;
  224. char *buf;
  225. if (!rx_stats)
  226. return -ENOENT;
  227. buf = kzalloc(size, GFP_KERNEL);
  228. if (!buf)
  229. return -ENOMEM;
  230. mutex_lock(&ar->conf_mutex);
  231. spin_lock_bh(&ar->ab->base_lock);
  232. len += scnprintf(buf + len, size - len, "RX peer stats:\n");
  233. len += scnprintf(buf + len, size - len, "Num of MSDUs: %llu\n",
  234. rx_stats->num_msdu);
  235. len += scnprintf(buf + len, size - len, "Num of MSDUs with TCP L4: %llu\n",
  236. rx_stats->tcp_msdu_count);
  237. len += scnprintf(buf + len, size - len, "Num of MSDUs with UDP L4: %llu\n",
  238. rx_stats->udp_msdu_count);
  239. len += scnprintf(buf + len, size - len, "Num of MSDUs part of AMPDU: %llu\n",
  240. rx_stats->ampdu_msdu_count);
  241. len += scnprintf(buf + len, size - len, "Num of MSDUs not part of AMPDU: %llu\n",
  242. rx_stats->non_ampdu_msdu_count);
  243. len += scnprintf(buf + len, size - len, "Num of MSDUs using STBC: %llu\n",
  244. rx_stats->stbc_count);
  245. len += scnprintf(buf + len, size - len, "Num of MSDUs beamformed: %llu\n",
  246. rx_stats->beamformed_count);
  247. len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS ok: %llu\n",
  248. rx_stats->num_mpdu_fcs_ok);
  249. len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS error: %llu\n",
  250. rx_stats->num_mpdu_fcs_err);
  251. len += scnprintf(buf + len, size - len,
  252. "GI: 0.8us %llu 0.4us %llu 1.6us %llu 3.2us %llu\n",
  253. rx_stats->gi_count[0], rx_stats->gi_count[1],
  254. rx_stats->gi_count[2], rx_stats->gi_count[3]);
  255. len += scnprintf(buf + len, size - len,
  256. "BW: 20Mhz %llu 40Mhz %llu 80Mhz %llu 160Mhz %llu\n",
  257. rx_stats->bw_count[0], rx_stats->bw_count[1],
  258. rx_stats->bw_count[2], rx_stats->bw_count[3]);
  259. len += scnprintf(buf + len, size - len, "BCC %llu LDPC %llu\n",
  260. rx_stats->coding_count[0], rx_stats->coding_count[1]);
  261. len += scnprintf(buf + len, size - len,
  262. "preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu\n",
  263. rx_stats->pream_cnt[0], rx_stats->pream_cnt[1],
  264. rx_stats->pream_cnt[2], rx_stats->pream_cnt[3],
  265. rx_stats->pream_cnt[4]);
  266. len += scnprintf(buf + len, size - len,
  267. "reception type: SU %llu MU_MIMO %llu MU_OFDMA %llu MU_OFDMA_MIMO %llu\n",
  268. rx_stats->reception_type[0], rx_stats->reception_type[1],
  269. rx_stats->reception_type[2], rx_stats->reception_type[3]);
  270. len += scnprintf(buf + len, size - len, "TID(0-15) Legacy TID(16):");
  271. for (i = 0; i <= IEEE80211_NUM_TIDS; i++)
  272. len += scnprintf(buf + len, size - len, "%llu ", rx_stats->tid_count[i]);
  273. len += scnprintf(buf + len, size - len, "\nMCS(0-11) Legacy MCS(12):");
  274. for (i = 0; i < HAL_RX_MAX_MCS + 1; i++)
  275. len += scnprintf(buf + len, size - len, "%llu ", rx_stats->mcs_count[i]);
  276. len += scnprintf(buf + len, size - len, "\nNSS(1-8):");
  277. for (i = 0; i < HAL_RX_MAX_NSS; i++)
  278. len += scnprintf(buf + len, size - len, "%llu ", rx_stats->nss_count[i]);
  279. len += scnprintf(buf + len, size - len, "\nRX Duration:%llu ",
  280. rx_stats->rx_duration);
  281. len += scnprintf(buf + len, size - len,
  282. "\nDCM: %llu\nRU: 26 %llu 52: %llu 106: %llu 242: %llu 484: %llu 996: %llu\n",
  283. rx_stats->dcm_count, rx_stats->ru_alloc_cnt[0],
  284. rx_stats->ru_alloc_cnt[1], rx_stats->ru_alloc_cnt[2],
  285. rx_stats->ru_alloc_cnt[3], rx_stats->ru_alloc_cnt[4],
  286. rx_stats->ru_alloc_cnt[5]);
  287. len += scnprintf(buf + len, size - len, "\n");
  288. spin_unlock_bh(&ar->ab->base_lock);
  289. if (len > size)
  290. len = size;
  291. retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
  292. kfree(buf);
  293. mutex_unlock(&ar->conf_mutex);
  294. return retval;
  295. }
  296. static const struct file_operations fops_rx_stats = {
  297. .read = ath11k_dbg_sta_dump_rx_stats,
  298. .open = simple_open,
  299. .owner = THIS_MODULE,
  300. .llseek = default_llseek,
  301. };
  302. static int
  303. ath11k_dbg_sta_open_htt_peer_stats(struct inode *inode, struct file *file)
  304. {
  305. struct ieee80211_sta *sta = inode->i_private;
  306. struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  307. struct ath11k *ar = arsta->arvif->ar;
  308. struct debug_htt_stats_req *stats_req;
  309. int type = ar->debug.htt_stats.type;
  310. int ret;
  311. if ((type != ATH11K_DBG_HTT_EXT_STATS_PEER_INFO &&
  312. type != ATH11K_DBG_HTT_EXT_STATS_PEER_CTRL_PATH_TXRX_STATS) ||
  313. type == ATH11K_DBG_HTT_EXT_STATS_RESET)
  314. return -EPERM;
  315. stats_req = vzalloc(sizeof(*stats_req) + ATH11K_HTT_STATS_BUF_SIZE);
  316. if (!stats_req)
  317. return -ENOMEM;
  318. mutex_lock(&ar->conf_mutex);
  319. ar->debug.htt_stats.stats_req = stats_req;
  320. stats_req->type = type;
  321. memcpy(stats_req->peer_addr, sta->addr, ETH_ALEN);
  322. ret = ath11k_debugfs_htt_stats_req(ar);
  323. mutex_unlock(&ar->conf_mutex);
  324. if (ret < 0)
  325. goto out;
  326. file->private_data = stats_req;
  327. return 0;
  328. out:
  329. vfree(stats_req);
  330. ar->debug.htt_stats.stats_req = NULL;
  331. return ret;
  332. }
  333. static int
  334. ath11k_dbg_sta_release_htt_peer_stats(struct inode *inode, struct file *file)
  335. {
  336. struct ieee80211_sta *sta = inode->i_private;
  337. struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  338. struct ath11k *ar = arsta->arvif->ar;
  339. mutex_lock(&ar->conf_mutex);
  340. vfree(file->private_data);
  341. ar->debug.htt_stats.stats_req = NULL;
  342. mutex_unlock(&ar->conf_mutex);
  343. return 0;
  344. }
  345. static ssize_t ath11k_dbg_sta_read_htt_peer_stats(struct file *file,
  346. char __user *user_buf,
  347. size_t count, loff_t *ppos)
  348. {
  349. struct debug_htt_stats_req *stats_req = file->private_data;
  350. char *buf;
  351. u32 length = 0;
  352. buf = stats_req->buf;
  353. length = min_t(u32, stats_req->buf_len, ATH11K_HTT_STATS_BUF_SIZE);
  354. return simple_read_from_buffer(user_buf, count, ppos, buf, length);
  355. }
  356. static const struct file_operations fops_htt_peer_stats = {
  357. .open = ath11k_dbg_sta_open_htt_peer_stats,
  358. .release = ath11k_dbg_sta_release_htt_peer_stats,
  359. .read = ath11k_dbg_sta_read_htt_peer_stats,
  360. .owner = THIS_MODULE,
  361. .llseek = default_llseek,
  362. };
  363. static ssize_t ath11k_dbg_sta_write_peer_pktlog(struct file *file,
  364. const char __user *buf,
  365. size_t count, loff_t *ppos)
  366. {
  367. struct ieee80211_sta *sta = file->private_data;
  368. struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  369. struct ath11k *ar = arsta->arvif->ar;
  370. int ret, enable;
  371. mutex_lock(&ar->conf_mutex);
  372. if (ar->state != ATH11K_STATE_ON) {
  373. ret = -ENETDOWN;
  374. goto out;
  375. }
  376. ret = kstrtoint_from_user(buf, count, 0, &enable);
  377. if (ret)
  378. goto out;
  379. ar->debug.pktlog_peer_valid = enable;
  380. memcpy(ar->debug.pktlog_peer_addr, sta->addr, ETH_ALEN);
  381. /* Send peer based pktlog enable/disable */
  382. ret = ath11k_wmi_pdev_peer_pktlog_filter(ar, sta->addr, enable);
  383. if (ret) {
  384. ath11k_warn(ar->ab, "failed to set peer pktlog filter %pM: %d\n",
  385. sta->addr, ret);
  386. goto out;
  387. }
  388. ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "peer pktlog filter set to %d\n",
  389. enable);
  390. ret = count;
  391. out:
  392. mutex_unlock(&ar->conf_mutex);
  393. return ret;
  394. }
  395. static ssize_t ath11k_dbg_sta_read_peer_pktlog(struct file *file,
  396. char __user *ubuf,
  397. size_t count, loff_t *ppos)
  398. {
  399. struct ieee80211_sta *sta = file->private_data;
  400. struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  401. struct ath11k *ar = arsta->arvif->ar;
  402. char buf[32] = {0};
  403. int len;
  404. mutex_lock(&ar->conf_mutex);
  405. len = scnprintf(buf, sizeof(buf), "%08x %pM\n",
  406. ar->debug.pktlog_peer_valid,
  407. ar->debug.pktlog_peer_addr);
  408. mutex_unlock(&ar->conf_mutex);
  409. return simple_read_from_buffer(ubuf, count, ppos, buf, len);
  410. }
  411. static const struct file_operations fops_peer_pktlog = {
  412. .write = ath11k_dbg_sta_write_peer_pktlog,
  413. .read = ath11k_dbg_sta_read_peer_pktlog,
  414. .open = simple_open,
  415. .owner = THIS_MODULE,
  416. .llseek = default_llseek,
  417. };
  418. static ssize_t ath11k_dbg_sta_write_delba(struct file *file,
  419. const char __user *user_buf,
  420. size_t count, loff_t *ppos)
  421. {
  422. struct ieee80211_sta *sta = file->private_data;
  423. struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  424. struct ath11k *ar = arsta->arvif->ar;
  425. u32 tid, initiator, reason;
  426. int ret;
  427. char buf[64] = {0};
  428. ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
  429. user_buf, count);
  430. if (ret <= 0)
  431. return ret;
  432. ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
  433. if (ret != 3)
  434. return -EINVAL;
  435. /* Valid TID values are 0 through 15 */
  436. if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
  437. return -EINVAL;
  438. mutex_lock(&ar->conf_mutex);
  439. if (ar->state != ATH11K_STATE_ON ||
  440. arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
  441. ret = count;
  442. goto out;
  443. }
  444. ret = ath11k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
  445. tid, initiator, reason);
  446. if (ret) {
  447. ath11k_warn(ar->ab, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
  448. arsta->arvif->vdev_id, sta->addr, tid, initiator,
  449. reason);
  450. }
  451. ret = count;
  452. out:
  453. mutex_unlock(&ar->conf_mutex);
  454. return ret;
  455. }
  456. static const struct file_operations fops_delba = {
  457. .write = ath11k_dbg_sta_write_delba,
  458. .open = simple_open,
  459. .owner = THIS_MODULE,
  460. .llseek = default_llseek,
  461. };
  462. static ssize_t ath11k_dbg_sta_write_addba_resp(struct file *file,
  463. const char __user *user_buf,
  464. size_t count, loff_t *ppos)
  465. {
  466. struct ieee80211_sta *sta = file->private_data;
  467. struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  468. struct ath11k *ar = arsta->arvif->ar;
  469. u32 tid, status;
  470. int ret;
  471. char buf[64] = {0};
  472. ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
  473. user_buf, count);
  474. if (ret <= 0)
  475. return ret;
  476. ret = sscanf(buf, "%u %u", &tid, &status);
  477. if (ret != 2)
  478. return -EINVAL;
  479. /* Valid TID values are 0 through 15 */
  480. if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
  481. return -EINVAL;
  482. mutex_lock(&ar->conf_mutex);
  483. if (ar->state != ATH11K_STATE_ON ||
  484. arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
  485. ret = count;
  486. goto out;
  487. }
  488. ret = ath11k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
  489. tid, status);
  490. if (ret) {
  491. ath11k_warn(ar->ab, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
  492. arsta->arvif->vdev_id, sta->addr, tid, status);
  493. }
  494. ret = count;
  495. out:
  496. mutex_unlock(&ar->conf_mutex);
  497. return ret;
  498. }
  499. static const struct file_operations fops_addba_resp = {
  500. .write = ath11k_dbg_sta_write_addba_resp,
  501. .open = simple_open,
  502. .owner = THIS_MODULE,
  503. .llseek = default_llseek,
  504. };
  505. static ssize_t ath11k_dbg_sta_write_addba(struct file *file,
  506. const char __user *user_buf,
  507. size_t count, loff_t *ppos)
  508. {
  509. struct ieee80211_sta *sta = file->private_data;
  510. struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  511. struct ath11k *ar = arsta->arvif->ar;
  512. u32 tid, buf_size;
  513. int ret;
  514. char buf[64] = {0};
  515. ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
  516. user_buf, count);
  517. if (ret <= 0)
  518. return ret;
  519. ret = sscanf(buf, "%u %u", &tid, &buf_size);
  520. if (ret != 2)
  521. return -EINVAL;
  522. /* Valid TID values are 0 through 15 */
  523. if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
  524. return -EINVAL;
  525. mutex_lock(&ar->conf_mutex);
  526. if (ar->state != ATH11K_STATE_ON ||
  527. arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
  528. ret = count;
  529. goto out;
  530. }
  531. ret = ath11k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
  532. tid, buf_size);
  533. if (ret) {
  534. ath11k_warn(ar->ab, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
  535. arsta->arvif->vdev_id, sta->addr, tid, buf_size);
  536. }
  537. ret = count;
  538. out:
  539. mutex_unlock(&ar->conf_mutex);
  540. return ret;
  541. }
  542. static const struct file_operations fops_addba = {
  543. .write = ath11k_dbg_sta_write_addba,
  544. .open = simple_open,
  545. .owner = THIS_MODULE,
  546. .llseek = default_llseek,
  547. };
  548. static ssize_t ath11k_dbg_sta_read_aggr_mode(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 ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  554. struct ath11k *ar = arsta->arvif->ar;
  555. char buf[64];
  556. int len = 0;
  557. mutex_lock(&ar->conf_mutex);
  558. len = scnprintf(buf, sizeof(buf) - len,
  559. "aggregation mode: %s\n\n%s\n%s\n",
  560. (arsta->aggr_mode == ATH11K_DBG_AGGR_MODE_AUTO) ?
  561. "auto" : "manual", "auto = 0", "manual = 1");
  562. mutex_unlock(&ar->conf_mutex);
  563. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  564. }
  565. static ssize_t ath11k_dbg_sta_write_aggr_mode(struct file *file,
  566. const char __user *user_buf,
  567. size_t count, loff_t *ppos)
  568. {
  569. struct ieee80211_sta *sta = file->private_data;
  570. struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  571. struct ath11k *ar = arsta->arvif->ar;
  572. u32 aggr_mode;
  573. int ret;
  574. if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode))
  575. return -EINVAL;
  576. if (aggr_mode >= ATH11K_DBG_AGGR_MODE_MAX)
  577. return -EINVAL;
  578. mutex_lock(&ar->conf_mutex);
  579. if (ar->state != ATH11K_STATE_ON ||
  580. aggr_mode == arsta->aggr_mode) {
  581. ret = count;
  582. goto out;
  583. }
  584. ret = ath11k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr);
  585. if (ret) {
  586. ath11k_warn(ar->ab, "failed to clear addba session ret: %d\n",
  587. ret);
  588. goto out;
  589. }
  590. arsta->aggr_mode = aggr_mode;
  591. out:
  592. mutex_unlock(&ar->conf_mutex);
  593. return ret;
  594. }
  595. static const struct file_operations fops_aggr_mode = {
  596. .read = ath11k_dbg_sta_read_aggr_mode,
  597. .write = ath11k_dbg_sta_write_aggr_mode,
  598. .open = simple_open,
  599. .owner = THIS_MODULE,
  600. .llseek = default_llseek,
  601. };
  602. static ssize_t
  603. ath11k_write_htt_peer_stats_reset(struct file *file,
  604. const char __user *user_buf,
  605. size_t count, loff_t *ppos)
  606. {
  607. struct ieee80211_sta *sta = file->private_data;
  608. struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  609. struct ath11k *ar = arsta->arvif->ar;
  610. struct htt_ext_stats_cfg_params cfg_params = { 0 };
  611. int ret;
  612. u8 type;
  613. ret = kstrtou8_from_user(user_buf, count, 0, &type);
  614. if (ret)
  615. return ret;
  616. if (!type)
  617. return ret;
  618. mutex_lock(&ar->conf_mutex);
  619. cfg_params.cfg0 = HTT_STAT_PEER_INFO_MAC_ADDR;
  620. cfg_params.cfg0 |= FIELD_PREP(GENMASK(15, 1),
  621. HTT_PEER_STATS_REQ_MODE_FLUSH_TQM);
  622. cfg_params.cfg1 = HTT_STAT_DEFAULT_PEER_REQ_TYPE;
  623. cfg_params.cfg2 |= FIELD_PREP(GENMASK(7, 0), sta->addr[0]);
  624. cfg_params.cfg2 |= FIELD_PREP(GENMASK(15, 8), sta->addr[1]);
  625. cfg_params.cfg2 |= FIELD_PREP(GENMASK(23, 16), sta->addr[2]);
  626. cfg_params.cfg2 |= FIELD_PREP(GENMASK(31, 24), sta->addr[3]);
  627. cfg_params.cfg3 |= FIELD_PREP(GENMASK(7, 0), sta->addr[4]);
  628. cfg_params.cfg3 |= FIELD_PREP(GENMASK(15, 8), sta->addr[5]);
  629. cfg_params.cfg3 |= ATH11K_HTT_PEER_STATS_RESET;
  630. ret = ath11k_dp_tx_htt_h2t_ext_stats_req(ar,
  631. ATH11K_DBG_HTT_EXT_STATS_PEER_INFO,
  632. &cfg_params,
  633. 0ULL);
  634. if (ret) {
  635. ath11k_warn(ar->ab, "failed to send htt peer stats request: %d\n", ret);
  636. mutex_unlock(&ar->conf_mutex);
  637. return ret;
  638. }
  639. mutex_unlock(&ar->conf_mutex);
  640. ret = count;
  641. return ret;
  642. }
  643. static const struct file_operations fops_htt_peer_stats_reset = {
  644. .write = ath11k_write_htt_peer_stats_reset,
  645. .open = simple_open,
  646. .owner = THIS_MODULE,
  647. .llseek = default_llseek,
  648. };
  649. static ssize_t ath11k_dbg_sta_read_peer_ps_state(struct file *file,
  650. char __user *user_buf,
  651. size_t count, loff_t *ppos)
  652. {
  653. struct ieee80211_sta *sta = file->private_data;
  654. struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  655. struct ath11k *ar = arsta->arvif->ar;
  656. char buf[20];
  657. int len;
  658. spin_lock_bh(&ar->data_lock);
  659. len = scnprintf(buf, sizeof(buf), "%d\n", arsta->peer_ps_state);
  660. spin_unlock_bh(&ar->data_lock);
  661. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  662. }
  663. static const struct file_operations fops_peer_ps_state = {
  664. .open = simple_open,
  665. .read = ath11k_dbg_sta_read_peer_ps_state,
  666. .owner = THIS_MODULE,
  667. .llseek = default_llseek,
  668. };
  669. static ssize_t ath11k_dbg_sta_read_current_ps_duration(struct file *file,
  670. char __user *user_buf,
  671. size_t count,
  672. loff_t *ppos)
  673. {
  674. struct ieee80211_sta *sta = file->private_data;
  675. struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  676. struct ath11k *ar = arsta->arvif->ar;
  677. u64 time_since_station_in_power_save;
  678. char buf[20];
  679. int len;
  680. spin_lock_bh(&ar->data_lock);
  681. if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON &&
  682. arsta->peer_current_ps_valid)
  683. time_since_station_in_power_save = jiffies_to_msecs(jiffies
  684. - arsta->ps_start_jiffies);
  685. else
  686. time_since_station_in_power_save = 0;
  687. len = scnprintf(buf, sizeof(buf), "%llu\n",
  688. time_since_station_in_power_save);
  689. spin_unlock_bh(&ar->data_lock);
  690. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  691. }
  692. static const struct file_operations fops_current_ps_duration = {
  693. .open = simple_open,
  694. .read = ath11k_dbg_sta_read_current_ps_duration,
  695. .owner = THIS_MODULE,
  696. .llseek = default_llseek,
  697. };
  698. static ssize_t ath11k_dbg_sta_read_total_ps_duration(struct file *file,
  699. char __user *user_buf,
  700. size_t count, loff_t *ppos)
  701. {
  702. struct ieee80211_sta *sta = file->private_data;
  703. struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
  704. struct ath11k *ar = arsta->arvif->ar;
  705. char buf[20];
  706. u64 power_save_duration;
  707. int len;
  708. spin_lock_bh(&ar->data_lock);
  709. if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON &&
  710. arsta->peer_current_ps_valid)
  711. power_save_duration = jiffies_to_msecs(jiffies
  712. - arsta->ps_start_jiffies)
  713. + arsta->ps_total_duration;
  714. else
  715. power_save_duration = arsta->ps_total_duration;
  716. len = scnprintf(buf, sizeof(buf), "%llu\n", power_save_duration);
  717. spin_unlock_bh(&ar->data_lock);
  718. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  719. }
  720. static const struct file_operations fops_total_ps_duration = {
  721. .open = simple_open,
  722. .read = ath11k_dbg_sta_read_total_ps_duration,
  723. .owner = THIS_MODULE,
  724. .llseek = default_llseek,
  725. };
  726. void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  727. struct ieee80211_sta *sta, struct dentry *dir)
  728. {
  729. struct ath11k *ar = hw->priv;
  730. if (ath11k_debugfs_is_extd_tx_stats_enabled(ar))
  731. debugfs_create_file("tx_stats", 0400, dir, sta,
  732. &fops_tx_stats);
  733. if (ath11k_debugfs_is_extd_rx_stats_enabled(ar))
  734. debugfs_create_file("rx_stats", 0400, dir, sta,
  735. &fops_rx_stats);
  736. debugfs_create_file("htt_peer_stats", 0400, dir, sta,
  737. &fops_htt_peer_stats);
  738. debugfs_create_file("peer_pktlog", 0644, dir, sta,
  739. &fops_peer_pktlog);
  740. debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
  741. debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
  742. debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
  743. debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
  744. if (test_bit(WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET,
  745. ar->ab->wmi_ab.svc_map))
  746. debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta,
  747. &fops_htt_peer_stats_reset);
  748. debugfs_create_file("peer_ps_state", 0400, dir, sta,
  749. &fops_peer_ps_state);
  750. if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,
  751. ar->ab->wmi_ab.svc_map)) {
  752. debugfs_create_file("current_ps_duration", 0440, dir, sta,
  753. &fops_current_ps_duration);
  754. debugfs_create_file("total_ps_duration", 0440, dir, sta,
  755. &fops_total_ps_duration);
  756. }
  757. }