diff options
author | Michal Kazior <michal.kazior@tieto.com> | 2015-02-15 09:50:40 -0500 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2015-02-15 09:50:40 -0500 |
commit | 7b6b153a7a9f4244740a0dab5238d207c1ee5422 (patch) | |
tree | 9624f5f79fddd30a779ef7458f1d881ba2c07fd9 /drivers/net/wireless | |
parent | 2c512059bb64296aca4ce99fec93c6561c52e26c (diff) |
ath10k: add vdev stats processing
New qca6174 wmi-tlv firmware supports vdev stats.
This patch adds support for it in the debug
frontend.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/core.h | 20 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/debug.c | 96 |
2 files changed, 116 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index d60e46fe6d19..7cba7815be96 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
@@ -159,6 +159,25 @@ struct ath10k_fw_stats_peer { | |||
159 | u32 peer_rx_rate; /* 10x only */ | 159 | u32 peer_rx_rate; /* 10x only */ |
160 | }; | 160 | }; |
161 | 161 | ||
162 | struct ath10k_fw_stats_vdev { | ||
163 | struct list_head list; | ||
164 | |||
165 | u32 vdev_id; | ||
166 | u32 beacon_snr; | ||
167 | u32 data_snr; | ||
168 | u32 num_tx_frames[4]; | ||
169 | u32 num_rx_frames; | ||
170 | u32 num_tx_frames_retries[4]; | ||
171 | u32 num_tx_frames_failures[4]; | ||
172 | u32 num_rts_fail; | ||
173 | u32 num_rts_success; | ||
174 | u32 num_rx_err; | ||
175 | u32 num_rx_discard; | ||
176 | u32 num_tx_not_acked; | ||
177 | u32 tx_rate_history[10]; | ||
178 | u32 beacon_rssi_history[10]; | ||
179 | }; | ||
180 | |||
162 | struct ath10k_fw_stats_pdev { | 181 | struct ath10k_fw_stats_pdev { |
163 | struct list_head list; | 182 | struct list_head list; |
164 | 183 | ||
@@ -220,6 +239,7 @@ struct ath10k_fw_stats_pdev { | |||
220 | 239 | ||
221 | struct ath10k_fw_stats { | 240 | struct ath10k_fw_stats { |
222 | struct list_head pdevs; | 241 | struct list_head pdevs; |
242 | struct list_head vdevs; | ||
223 | struct list_head peers; | 243 | struct list_head peers; |
224 | }; | 244 | }; |
225 | 245 | ||
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index d2281e5c2ffe..8e969c9d9d5f 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c | |||
@@ -243,6 +243,16 @@ static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head) | |||
243 | } | 243 | } |
244 | } | 244 | } |
245 | 245 | ||
246 | static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head) | ||
247 | { | ||
248 | struct ath10k_fw_stats_vdev *i, *tmp; | ||
249 | |||
250 | list_for_each_entry_safe(i, tmp, head, list) { | ||
251 | list_del(&i->list); | ||
252 | kfree(i); | ||
253 | } | ||
254 | } | ||
255 | |||
246 | static void ath10k_debug_fw_stats_peers_free(struct list_head *head) | 256 | static void ath10k_debug_fw_stats_peers_free(struct list_head *head) |
247 | { | 257 | { |
248 | struct ath10k_fw_stats_peer *i, *tmp; | 258 | struct ath10k_fw_stats_peer *i, *tmp; |
@@ -258,6 +268,7 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar) | |||
258 | spin_lock_bh(&ar->data_lock); | 268 | spin_lock_bh(&ar->data_lock); |
259 | ar->debug.fw_stats_done = false; | 269 | ar->debug.fw_stats_done = false; |
260 | ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs); | 270 | ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs); |
271 | ath10k_debug_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs); | ||
261 | ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers); | 272 | ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers); |
262 | spin_unlock_bh(&ar->data_lock); | 273 | spin_unlock_bh(&ar->data_lock); |
263 | } | 274 | } |
@@ -273,14 +284,27 @@ static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head) | |||
273 | return num; | 284 | return num; |
274 | } | 285 | } |
275 | 286 | ||
287 | static size_t ath10k_debug_fw_stats_num_vdevs(struct list_head *head) | ||
288 | { | ||
289 | struct ath10k_fw_stats_vdev *i; | ||
290 | size_t num = 0; | ||
291 | |||
292 | list_for_each_entry(i, head, list) | ||
293 | ++num; | ||
294 | |||
295 | return num; | ||
296 | } | ||
297 | |||
276 | void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) | 298 | void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) |
277 | { | 299 | { |
278 | struct ath10k_fw_stats stats = {}; | 300 | struct ath10k_fw_stats stats = {}; |
279 | bool is_start, is_started, is_end; | 301 | bool is_start, is_started, is_end; |
280 | size_t num_peers; | 302 | size_t num_peers; |
303 | size_t num_vdevs; | ||
281 | int ret; | 304 | int ret; |
282 | 305 | ||
283 | INIT_LIST_HEAD(&stats.pdevs); | 306 | INIT_LIST_HEAD(&stats.pdevs); |
307 | INIT_LIST_HEAD(&stats.vdevs); | ||
284 | INIT_LIST_HEAD(&stats.peers); | 308 | INIT_LIST_HEAD(&stats.peers); |
285 | 309 | ||
286 | spin_lock_bh(&ar->data_lock); | 310 | spin_lock_bh(&ar->data_lock); |
@@ -308,6 +332,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) | |||
308 | } | 332 | } |
309 | 333 | ||
310 | num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers); | 334 | num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers); |
335 | num_vdevs = ath10k_debug_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs); | ||
311 | is_start = (list_empty(&ar->debug.fw_stats.pdevs) && | 336 | is_start = (list_empty(&ar->debug.fw_stats.pdevs) && |
312 | !list_empty(&stats.pdevs)); | 337 | !list_empty(&stats.pdevs)); |
313 | is_end = (!list_empty(&ar->debug.fw_stats.pdevs) && | 338 | is_end = (!list_empty(&ar->debug.fw_stats.pdevs) && |
@@ -330,7 +355,13 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) | |||
330 | goto free; | 355 | goto free; |
331 | } | 356 | } |
332 | 357 | ||
358 | if (num_vdevs >= BITS_PER_LONG) { | ||
359 | ath10k_warn(ar, "dropping fw vdev stats\n"); | ||
360 | goto free; | ||
361 | } | ||
362 | |||
333 | list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers); | 363 | list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers); |
364 | list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs); | ||
334 | } | 365 | } |
335 | 366 | ||
336 | complete(&ar->debug.fw_stats_complete); | 367 | complete(&ar->debug.fw_stats_complete); |
@@ -340,6 +371,7 @@ free: | |||
340 | * resources if that is not the case. | 371 | * resources if that is not the case. |
341 | */ | 372 | */ |
342 | ath10k_debug_fw_stats_pdevs_free(&stats.pdevs); | 373 | ath10k_debug_fw_stats_pdevs_free(&stats.pdevs); |
374 | ath10k_debug_fw_stats_vdevs_free(&stats.vdevs); | ||
343 | ath10k_debug_fw_stats_peers_free(&stats.peers); | 375 | ath10k_debug_fw_stats_peers_free(&stats.peers); |
344 | 376 | ||
345 | unlock: | 377 | unlock: |
@@ -395,8 +427,11 @@ static void ath10k_fw_stats_fill(struct ath10k *ar, | |||
395 | unsigned int len = 0; | 427 | unsigned int len = 0; |
396 | unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE; | 428 | unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE; |
397 | const struct ath10k_fw_stats_pdev *pdev; | 429 | const struct ath10k_fw_stats_pdev *pdev; |
430 | const struct ath10k_fw_stats_vdev *vdev; | ||
398 | const struct ath10k_fw_stats_peer *peer; | 431 | const struct ath10k_fw_stats_peer *peer; |
399 | size_t num_peers; | 432 | size_t num_peers; |
433 | size_t num_vdevs; | ||
434 | int i; | ||
400 | 435 | ||
401 | spin_lock_bh(&ar->data_lock); | 436 | spin_lock_bh(&ar->data_lock); |
402 | 437 | ||
@@ -408,6 +443,7 @@ static void ath10k_fw_stats_fill(struct ath10k *ar, | |||
408 | } | 443 | } |
409 | 444 | ||
410 | num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers); | 445 | num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers); |
446 | num_vdevs = ath10k_debug_fw_stats_num_vdevs(&fw_stats->vdevs); | ||
411 | 447 | ||
412 | len += scnprintf(buf + len, buf_len - len, "\n"); | 448 | len += scnprintf(buf + len, buf_len - len, "\n"); |
413 | len += scnprintf(buf + len, buf_len - len, "%30s\n", | 449 | len += scnprintf(buf + len, buf_len - len, "%30s\n", |
@@ -531,6 +567,65 @@ static void ath10k_fw_stats_fill(struct ath10k *ar, | |||
531 | 567 | ||
532 | len += scnprintf(buf + len, buf_len - len, "\n"); | 568 | len += scnprintf(buf + len, buf_len - len, "\n"); |
533 | len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", | 569 | len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", |
570 | "ath10k VDEV stats", num_vdevs); | ||
571 | len += scnprintf(buf + len, buf_len - len, "%30s\n\n", | ||
572 | "================="); | ||
573 | |||
574 | list_for_each_entry(vdev, &fw_stats->vdevs, list) { | ||
575 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | ||
576 | "vdev id", vdev->vdev_id); | ||
577 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | ||
578 | "beacon snr", vdev->beacon_snr); | ||
579 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | ||
580 | "data snr", vdev->data_snr); | ||
581 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | ||
582 | "num rx frames", vdev->num_rx_frames); | ||
583 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | ||
584 | "num rts fail", vdev->num_rts_fail); | ||
585 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | ||
586 | "num rts success", vdev->num_rts_success); | ||
587 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | ||
588 | "num rx err", vdev->num_rx_err); | ||
589 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | ||
590 | "num rx discard", vdev->num_rx_discard); | ||
591 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | ||
592 | "num tx not acked", vdev->num_tx_not_acked); | ||
593 | |||
594 | for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames); i++) | ||
595 | len += scnprintf(buf + len, buf_len - len, | ||
596 | "%25s [%02d] %u\n", | ||
597 | "num tx frames", i, | ||
598 | vdev->num_tx_frames[i]); | ||
599 | |||
600 | for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_retries); i++) | ||
601 | len += scnprintf(buf + len, buf_len - len, | ||
602 | "%25s [%02d] %u\n", | ||
603 | "num tx frames retries", i, | ||
604 | vdev->num_tx_frames_retries[i]); | ||
605 | |||
606 | for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_failures); i++) | ||
607 | len += scnprintf(buf + len, buf_len - len, | ||
608 | "%25s [%02d] %u\n", | ||
609 | "num tx frames failures", i, | ||
610 | vdev->num_tx_frames_failures[i]); | ||
611 | |||
612 | for (i = 0 ; i < ARRAY_SIZE(vdev->tx_rate_history); i++) | ||
613 | len += scnprintf(buf + len, buf_len - len, | ||
614 | "%25s [%02d] 0x%08x\n", | ||
615 | "tx rate history", i, | ||
616 | vdev->tx_rate_history[i]); | ||
617 | |||
618 | for (i = 0 ; i < ARRAY_SIZE(vdev->beacon_rssi_history); i++) | ||
619 | len += scnprintf(buf + len, buf_len - len, | ||
620 | "%25s [%02d] %u\n", | ||
621 | "beacon rssi history", i, | ||
622 | vdev->beacon_rssi_history[i]); | ||
623 | |||
624 | len += scnprintf(buf + len, buf_len - len, "\n"); | ||
625 | } | ||
626 | |||
627 | len += scnprintf(buf + len, buf_len - len, "\n"); | ||
628 | len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", | ||
534 | "ath10k PEER stats", num_peers); | 629 | "ath10k PEER stats", num_peers); |
535 | len += scnprintf(buf + len, buf_len - len, "%30s\n\n", | 630 | len += scnprintf(buf + len, buf_len - len, "%30s\n\n", |
536 | "================="); | 631 | "================="); |
@@ -1900,6 +1995,7 @@ int ath10k_debug_create(struct ath10k *ar) | |||
1900 | return -ENOMEM; | 1995 | return -ENOMEM; |
1901 | 1996 | ||
1902 | INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs); | 1997 | INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs); |
1998 | INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs); | ||
1903 | INIT_LIST_HEAD(&ar->debug.fw_stats.peers); | 1999 | INIT_LIST_HEAD(&ar->debug.fw_stats.peers); |
1904 | 2000 | ||
1905 | return 0; | 2001 | return 0; |