aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorBen Greear <greearb@candelatech.com>2012-04-23 15:50:32 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-05-08 21:53:52 -0400
commit3073a7c20cea0b7a9946fe61f09d43aa61deb9ea (patch)
tree4f9317a18a31e81e08885a7c9c79ed0c836c3413 /net/mac80211
parente352114fd62f6d568ca0cb18f589cb8df710cf02 (diff)
mac80211: Add more ethtools stats: survey, rates, etc
The signal and noise are forced to be positive since ethtool deals in unsigned 64-bit values and this number should be human readable. This gives easy access to some of the data formerly exposed in the deprecated /proc/net/wireless file. Signed-off-by: Ben Greear <greearb@candelatech.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c89
1 files changed, 81 insertions, 8 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a38b26730652..39b1fffb24f4 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -455,7 +455,9 @@ static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
455 "rx_duplicates", "rx_fragments", "rx_dropped", 455 "rx_duplicates", "rx_fragments", "rx_dropped",
456 "tx_packets", "tx_bytes", "tx_fragments", 456 "tx_packets", "tx_bytes", "tx_fragments",
457 "tx_filtered", "tx_retry_failed", "tx_retries", 457 "tx_filtered", "tx_retry_failed", "tx_retries",
458 "beacon_loss" 458 "beacon_loss", "sta_state", "txrate", "rxrate", "signal",
459 "channel", "noise", "ch_time", "ch_time_busy",
460 "ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
459}; 461};
460#define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats) 462#define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats)
461 463
@@ -484,7 +486,10 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
484 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 486 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
485 struct sta_info *sta; 487 struct sta_info *sta;
486 struct ieee80211_local *local = sdata->local; 488 struct ieee80211_local *local = sdata->local;
487 int i; 489 struct station_info sinfo;
490 struct survey_info survey;
491 int i, q;
492#define STA_STATS_SURVEY_LEN 7
488 493
489 memset(data, 0, sizeof(u64) * STA_STATS_LEN); 494 memset(data, 0, sizeof(u64) * STA_STATS_LEN);
490 495
@@ -516,11 +521,30 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
516 521
517 if (sdata->vif.type == NL80211_IFTYPE_STATION) { 522 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
518 sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid); 523 sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid);
519 if (sta && !WARN_ON(sta->sdata->dev != dev)) { 524
520 i = 0; 525 if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
521 ADD_STA_STATS(sta); 526 goto do_survey;
522 BUG_ON(i != STA_STATS_LEN); 527
523 } 528 i = 0;
529 ADD_STA_STATS(sta);
530
531 data[i++] = sta->sta_state;
532
533 sinfo.filled = 0;
534 sta_set_sinfo(sta, &sinfo);
535
536 if (sinfo.filled | STATION_INFO_TX_BITRATE)
537 data[i] = 100000 *
538 cfg80211_calculate_bitrate(&sinfo.txrate);
539 i++;
540 if (sinfo.filled | STATION_INFO_RX_BITRATE)
541 data[i] = 100000 *
542 cfg80211_calculate_bitrate(&sinfo.rxrate);
543 i++;
544
545 if (sinfo.filled | STATION_INFO_SIGNAL_AVG)
546 data[i] = (u8)sinfo.signal_avg;
547 i++;
524 } else { 548 } else {
525 list_for_each_entry_rcu(sta, &local->sta_list, list) { 549 list_for_each_entry_rcu(sta, &local->sta_list, list) {
526 /* Make sure this station belongs to the proper dev */ 550 /* Make sure this station belongs to the proper dev */
@@ -529,12 +553,61 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
529 553
530 i = 0; 554 i = 0;
531 ADD_STA_STATS(sta); 555 ADD_STA_STATS(sta);
532 BUG_ON(i != STA_STATS_LEN);
533 } 556 }
534 } 557 }
535 558
559do_survey:
560 i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
561 /* Get survey stats for current channel */
562 q = 0;
563 while (true) {
564 survey.filled = 0;
565 if (drv_get_survey(local, q, &survey) != 0) {
566 survey.filled = 0;
567 break;
568 }
569
570 if (survey.channel &&
571 (local->oper_channel->center_freq ==
572 survey.channel->center_freq))
573 break;
574 q++;
575 }
576
577 if (survey.filled)
578 data[i++] = survey.channel->center_freq;
579 else
580 data[i++] = 0;
581 if (survey.filled & SURVEY_INFO_NOISE_DBM)
582 data[i++] = (u8)survey.noise;
583 else
584 data[i++] = -1LL;
585 if (survey.filled & SURVEY_INFO_CHANNEL_TIME)
586 data[i++] = survey.channel_time;
587 else
588 data[i++] = -1LL;
589 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
590 data[i++] = survey.channel_time_busy;
591 else
592 data[i++] = -1LL;
593 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
594 data[i++] = survey.channel_time_ext_busy;
595 else
596 data[i++] = -1LL;
597 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX)
598 data[i++] = survey.channel_time_rx;
599 else
600 data[i++] = -1LL;
601 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX)
602 data[i++] = survey.channel_time_tx;
603 else
604 data[i++] = -1LL;
605
536 rcu_read_unlock(); 606 rcu_read_unlock();
537 607
608 if (WARN_ON(i != STA_STATS_LEN))
609 return;
610
538 drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN])); 611 drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
539} 612}
540 613