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