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