aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2015-02-15 09:50:40 -0500
committerKalle Valo <kvalo@qca.qualcomm.com>2015-02-15 09:50:40 -0500
commit7b6b153a7a9f4244740a0dab5238d207c1ee5422 (patch)
tree9624f5f79fddd30a779ef7458f1d881ba2c07fd9 /drivers/net/wireless
parent2c512059bb64296aca4ce99fec93c6561c52e26c (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.h20
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c96
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
162struct 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
162struct ath10k_fw_stats_pdev { 181struct 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
221struct ath10k_fw_stats { 240struct 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
246static 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
246static void ath10k_debug_fw_stats_peers_free(struct list_head *head) 256static 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
287static 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
276void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) 298void 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
345unlock: 377unlock:
@@ -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;