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/ath/ath10k | |
| 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/ath/ath10k')
| -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; |
