aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2014-06-04 11:31:56 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-06-23 05:05:33 -0400
commitb7ffbd7ef6751f6cde73082346e365738daf00d2 (patch)
tree849c2b771a45b68a6733698c5de030ae100de952 /net/mac80211
parentba9030c20a2def223d9b993cb3dfdd3aab3d2b31 (diff)
cfg80211: make ethtool the driver's responsibility
Currently, cfg80211 tries to implement ethtool, but that doesn't really scale well, with all the different operations. Make the lower-level driver responsible for it, which currently only has an effect on mac80211. It will similarly not scale well at that level though, since mac80211 also has many drivers. To cleanly implement this in mac80211, introduce a new file and move some code to appropriate places. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/Makefile1
-rw-r--r--net/mac80211/cfg.c340
-rw-r--r--net/mac80211/ethtool.c244
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/iface.c2
-rw-r--r--net/mac80211/sta_info.c134
-rw-r--r--net/mac80211/sta_info.h2
7 files changed, 385 insertions, 340 deletions
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 4409bf506594..7273d2796dd1 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -17,6 +17,7 @@ mac80211-y := \
17 aes_ccm.o \ 17 aes_ccm.o \
18 aes_cmac.o \ 18 aes_cmac.o \
19 cfg.o \ 19 cfg.o \
20 ethtool.o \
20 rx.o \ 21 rx.o \
21 spectmgmt.o \ 22 spectmgmt.o \
22 tx.o \ 23 tx.o \
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index f8d065480ba9..b6d73c14e1ae 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -468,326 +468,6 @@ void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
468 rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; 468 rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
469} 469}
470 470
471static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
472{
473 struct ieee80211_sub_if_data *sdata = sta->sdata;
474 struct ieee80211_local *local = sdata->local;
475 struct rate_control_ref *ref = local->rate_ctrl;
476 struct timespec uptime;
477 u64 packets = 0;
478 u32 thr = 0;
479 int i, ac;
480
481 sinfo->generation = sdata->local->sta_generation;
482
483 sinfo->filled = STATION_INFO_INACTIVE_TIME |
484 STATION_INFO_RX_BYTES64 |
485 STATION_INFO_TX_BYTES64 |
486 STATION_INFO_RX_PACKETS |
487 STATION_INFO_TX_PACKETS |
488 STATION_INFO_TX_RETRIES |
489 STATION_INFO_TX_FAILED |
490 STATION_INFO_TX_BITRATE |
491 STATION_INFO_RX_BITRATE |
492 STATION_INFO_RX_DROP_MISC |
493 STATION_INFO_BSS_PARAM |
494 STATION_INFO_CONNECTED_TIME |
495 STATION_INFO_STA_FLAGS |
496 STATION_INFO_BEACON_LOSS_COUNT;
497
498 do_posix_clock_monotonic_gettime(&uptime);
499 sinfo->connected_time = uptime.tv_sec - sta->last_connected;
500
501 sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
502 sinfo->tx_bytes = 0;
503 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
504 sinfo->tx_bytes += sta->tx_bytes[ac];
505 packets += sta->tx_packets[ac];
506 }
507 sinfo->tx_packets = packets;
508 sinfo->rx_bytes = sta->rx_bytes;
509 sinfo->rx_packets = sta->rx_packets;
510 sinfo->tx_retries = sta->tx_retry_count;
511 sinfo->tx_failed = sta->tx_retry_failed;
512 sinfo->rx_dropped_misc = sta->rx_dropped;
513 sinfo->beacon_loss_count = sta->beacon_loss_count;
514
515 if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
516 (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
517 sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG;
518 if (!local->ops->get_rssi ||
519 drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal))
520 sinfo->signal = (s8)sta->last_signal;
521 sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
522 }
523 if (sta->chains) {
524 sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
525 STATION_INFO_CHAIN_SIGNAL_AVG;
526
527 sinfo->chains = sta->chains;
528 for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
529 sinfo->chain_signal[i] = sta->chain_signal_last[i];
530 sinfo->chain_signal_avg[i] =
531 (s8) -ewma_read(&sta->chain_signal_avg[i]);
532 }
533 }
534
535 sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
536 sta_set_rate_info_rx(sta, &sinfo->rxrate);
537
538 if (ieee80211_vif_is_mesh(&sdata->vif)) {
539#ifdef CONFIG_MAC80211_MESH
540 sinfo->filled |= STATION_INFO_LLID |
541 STATION_INFO_PLID |
542 STATION_INFO_PLINK_STATE |
543 STATION_INFO_LOCAL_PM |
544 STATION_INFO_PEER_PM |
545 STATION_INFO_NONPEER_PM;
546
547 sinfo->llid = sta->llid;
548 sinfo->plid = sta->plid;
549 sinfo->plink_state = sta->plink_state;
550 if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
551 sinfo->filled |= STATION_INFO_T_OFFSET;
552 sinfo->t_offset = sta->t_offset;
553 }
554 sinfo->local_pm = sta->local_pm;
555 sinfo->peer_pm = sta->peer_pm;
556 sinfo->nonpeer_pm = sta->nonpeer_pm;
557#endif
558 }
559
560 sinfo->bss_param.flags = 0;
561 if (sdata->vif.bss_conf.use_cts_prot)
562 sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
563 if (sdata->vif.bss_conf.use_short_preamble)
564 sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
565 if (sdata->vif.bss_conf.use_short_slot)
566 sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
567 sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period;
568 sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int;
569
570 sinfo->sta_flags.set = 0;
571 sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
572 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
573 BIT(NL80211_STA_FLAG_WME) |
574 BIT(NL80211_STA_FLAG_MFP) |
575 BIT(NL80211_STA_FLAG_AUTHENTICATED) |
576 BIT(NL80211_STA_FLAG_ASSOCIATED) |
577 BIT(NL80211_STA_FLAG_TDLS_PEER);
578 if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
579 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
580 if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE))
581 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
582 if (test_sta_flag(sta, WLAN_STA_WME))
583 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME);
584 if (test_sta_flag(sta, WLAN_STA_MFP))
585 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP);
586 if (test_sta_flag(sta, WLAN_STA_AUTH))
587 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
588 if (test_sta_flag(sta, WLAN_STA_ASSOC))
589 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
590 if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
591 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
592
593 /* check if the driver has a SW RC implementation */
594 if (ref && ref->ops->get_expected_throughput)
595 thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
596 else
597 thr = drv_get_expected_throughput(local, &sta->sta);
598
599 if (thr != 0) {
600 sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT;
601 sinfo->expected_throughput = thr;
602 }
603}
604
605static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
606 "rx_packets", "rx_bytes",
607 "rx_duplicates", "rx_fragments", "rx_dropped",
608 "tx_packets", "tx_bytes", "tx_fragments",
609 "tx_filtered", "tx_retry_failed", "tx_retries",
610 "beacon_loss", "sta_state", "txrate", "rxrate", "signal",
611 "channel", "noise", "ch_time", "ch_time_busy",
612 "ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
613};
614#define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats)
615
616static int ieee80211_get_et_sset_count(struct wiphy *wiphy,
617 struct net_device *dev,
618 int sset)
619{
620 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
621 int rv = 0;
622
623 if (sset == ETH_SS_STATS)
624 rv += STA_STATS_LEN;
625
626 rv += drv_get_et_sset_count(sdata, sset);
627
628 if (rv == 0)
629 return -EOPNOTSUPP;
630 return rv;
631}
632
633static void ieee80211_get_et_stats(struct wiphy *wiphy,
634 struct net_device *dev,
635 struct ethtool_stats *stats,
636 u64 *data)
637{
638 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
639 struct ieee80211_chanctx_conf *chanctx_conf;
640 struct ieee80211_channel *channel;
641 struct sta_info *sta;
642 struct ieee80211_local *local = sdata->local;
643 struct station_info sinfo;
644 struct survey_info survey;
645 int i, q;
646#define STA_STATS_SURVEY_LEN 7
647
648 memset(data, 0, sizeof(u64) * STA_STATS_LEN);
649
650#define ADD_STA_STATS(sta) \
651 do { \
652 data[i++] += sta->rx_packets; \
653 data[i++] += sta->rx_bytes; \
654 data[i++] += sta->num_duplicates; \
655 data[i++] += sta->rx_fragments; \
656 data[i++] += sta->rx_dropped; \
657 \
658 data[i++] += sinfo.tx_packets; \
659 data[i++] += sinfo.tx_bytes; \
660 data[i++] += sta->tx_fragments; \
661 data[i++] += sta->tx_filtered_count; \
662 data[i++] += sta->tx_retry_failed; \
663 data[i++] += sta->tx_retry_count; \
664 data[i++] += sta->beacon_loss_count; \
665 } while (0)
666
667 /* For Managed stations, find the single station based on BSSID
668 * and use that. For interface types, iterate through all available
669 * stations and add stats for any station that is assigned to this
670 * network device.
671 */
672
673 mutex_lock(&local->sta_mtx);
674
675 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
676 sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid);
677
678 if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
679 goto do_survey;
680
681 sinfo.filled = 0;
682 sta_set_sinfo(sta, &sinfo);
683
684 i = 0;
685 ADD_STA_STATS(sta);
686
687 data[i++] = sta->sta_state;
688
689
690 if (sinfo.filled & STATION_INFO_TX_BITRATE)
691 data[i] = 100000 *
692 cfg80211_calculate_bitrate(&sinfo.txrate);
693 i++;
694 if (sinfo.filled & STATION_INFO_RX_BITRATE)
695 data[i] = 100000 *
696 cfg80211_calculate_bitrate(&sinfo.rxrate);
697 i++;
698
699 if (sinfo.filled & STATION_INFO_SIGNAL_AVG)
700 data[i] = (u8)sinfo.signal_avg;
701 i++;
702 } else {
703 list_for_each_entry(sta, &local->sta_list, list) {
704 /* Make sure this station belongs to the proper dev */
705 if (sta->sdata->dev != dev)
706 continue;
707
708 sinfo.filled = 0;
709 sta_set_sinfo(sta, &sinfo);
710 i = 0;
711 ADD_STA_STATS(sta);
712 }
713 }
714
715do_survey:
716 i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
717 /* Get survey stats for current channel */
718 survey.filled = 0;
719
720 rcu_read_lock();
721 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
722 if (chanctx_conf)
723 channel = chanctx_conf->def.chan;
724 else
725 channel = NULL;
726 rcu_read_unlock();
727
728 if (channel) {
729 q = 0;
730 do {
731 survey.filled = 0;
732 if (drv_get_survey(local, q, &survey) != 0) {
733 survey.filled = 0;
734 break;
735 }
736 q++;
737 } while (channel != survey.channel);
738 }
739
740 if (survey.filled)
741 data[i++] = survey.channel->center_freq;
742 else
743 data[i++] = 0;
744 if (survey.filled & SURVEY_INFO_NOISE_DBM)
745 data[i++] = (u8)survey.noise;
746 else
747 data[i++] = -1LL;
748 if (survey.filled & SURVEY_INFO_CHANNEL_TIME)
749 data[i++] = survey.channel_time;
750 else
751 data[i++] = -1LL;
752 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
753 data[i++] = survey.channel_time_busy;
754 else
755 data[i++] = -1LL;
756 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
757 data[i++] = survey.channel_time_ext_busy;
758 else
759 data[i++] = -1LL;
760 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX)
761 data[i++] = survey.channel_time_rx;
762 else
763 data[i++] = -1LL;
764 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX)
765 data[i++] = survey.channel_time_tx;
766 else
767 data[i++] = -1LL;
768
769 mutex_unlock(&local->sta_mtx);
770
771 if (WARN_ON(i != STA_STATS_LEN))
772 return;
773
774 drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
775}
776
777static void ieee80211_get_et_strings(struct wiphy *wiphy,
778 struct net_device *dev,
779 u32 sset, u8 *data)
780{
781 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
782 int sz_sta_stats = 0;
783
784 if (sset == ETH_SS_STATS) {
785 sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
786 memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats);
787 }
788 drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));
789}
790
791static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, 471static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
792 int idx, u8 *mac, struct station_info *sinfo) 472 int idx, u8 *mac, struct station_info *sinfo)
793{ 473{
@@ -3597,21 +3277,6 @@ static int ieee80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant)
3597 return drv_get_antenna(local, tx_ant, rx_ant); 3277 return drv_get_antenna(local, tx_ant, rx_ant);
3598} 3278}
3599 3279
3600static int ieee80211_set_ringparam(struct wiphy *wiphy, u32 tx, u32 rx)
3601{
3602 struct ieee80211_local *local = wiphy_priv(wiphy);
3603
3604 return drv_set_ringparam(local, tx, rx);
3605}
3606
3607static void ieee80211_get_ringparam(struct wiphy *wiphy,
3608 u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
3609{
3610 struct ieee80211_local *local = wiphy_priv(wiphy);
3611
3612 drv_get_ringparam(local, tx, tx_max, rx, rx_max);
3613}
3614
3615static int ieee80211_set_rekey_data(struct wiphy *wiphy, 3280static int ieee80211_set_rekey_data(struct wiphy *wiphy,
3616 struct net_device *dev, 3281 struct net_device *dev,
3617 struct cfg80211_gtk_rekey_data *data) 3282 struct cfg80211_gtk_rekey_data *data)
@@ -3843,8 +3508,6 @@ const struct cfg80211_ops mac80211_config_ops = {
3843 .mgmt_frame_register = ieee80211_mgmt_frame_register, 3508 .mgmt_frame_register = ieee80211_mgmt_frame_register,
3844 .set_antenna = ieee80211_set_antenna, 3509 .set_antenna = ieee80211_set_antenna,
3845 .get_antenna = ieee80211_get_antenna, 3510 .get_antenna = ieee80211_get_antenna,
3846 .set_ringparam = ieee80211_set_ringparam,
3847 .get_ringparam = ieee80211_get_ringparam,
3848 .set_rekey_data = ieee80211_set_rekey_data, 3511 .set_rekey_data = ieee80211_set_rekey_data,
3849 .tdls_oper = ieee80211_tdls_oper, 3512 .tdls_oper = ieee80211_tdls_oper,
3850 .tdls_mgmt = ieee80211_tdls_mgmt, 3513 .tdls_mgmt = ieee80211_tdls_mgmt,
@@ -3853,9 +3516,6 @@ const struct cfg80211_ops mac80211_config_ops = {
3853#ifdef CONFIG_PM 3516#ifdef CONFIG_PM
3854 .set_wakeup = ieee80211_set_wakeup, 3517 .set_wakeup = ieee80211_set_wakeup,
3855#endif 3518#endif
3856 .get_et_sset_count = ieee80211_get_et_sset_count,
3857 .get_et_stats = ieee80211_get_et_stats,
3858 .get_et_strings = ieee80211_get_et_strings,
3859 .get_channel = ieee80211_cfg_get_channel, 3519 .get_channel = ieee80211_cfg_get_channel,
3860 .start_radar_detection = ieee80211_start_radar_detection, 3520 .start_radar_detection = ieee80211_start_radar_detection,
3861 .channel_switch = ieee80211_channel_switch, 3521 .channel_switch = ieee80211_channel_switch,
diff --git a/net/mac80211/ethtool.c b/net/mac80211/ethtool.c
new file mode 100644
index 000000000000..ebfc8091557b
--- /dev/null
+++ b/net/mac80211/ethtool.c
@@ -0,0 +1,244 @@
1/*
2 * mac80211 ethtool hooks for cfg80211
3 *
4 * Copied from cfg.c - originally
5 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
6 * Copyright 2014 Intel Corporation (Author: Johannes Berg)
7 *
8 * This file is GPLv2 as found in COPYING.
9 */
10#include <linux/types.h>
11#include <net/cfg80211.h>
12#include "ieee80211_i.h"
13#include "sta_info.h"
14#include "driver-ops.h"
15
16static int ieee80211_set_ringparam(struct net_device *dev,
17 struct ethtool_ringparam *rp)
18{
19 struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy);
20
21 if (rp->rx_mini_pending != 0 || rp->rx_jumbo_pending != 0)
22 return -EINVAL;
23
24 return drv_set_ringparam(local, rp->tx_pending, rp->rx_pending);
25}
26
27static void ieee80211_get_ringparam(struct net_device *dev,
28 struct ethtool_ringparam *rp)
29{
30 struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy);
31
32 memset(rp, 0, sizeof(*rp));
33
34 drv_get_ringparam(local, &rp->tx_pending, &rp->tx_max_pending,
35 &rp->rx_pending, &rp->rx_max_pending);
36}
37
38static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
39 "rx_packets", "rx_bytes",
40 "rx_duplicates", "rx_fragments", "rx_dropped",
41 "tx_packets", "tx_bytes", "tx_fragments",
42 "tx_filtered", "tx_retry_failed", "tx_retries",
43 "beacon_loss", "sta_state", "txrate", "rxrate", "signal",
44 "channel", "noise", "ch_time", "ch_time_busy",
45 "ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
46};
47#define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats)
48
49static int ieee80211_get_sset_count(struct net_device *dev, int sset)
50{
51 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
52 int rv = 0;
53
54 if (sset == ETH_SS_STATS)
55 rv += STA_STATS_LEN;
56
57 rv += drv_get_et_sset_count(sdata, sset);
58
59 if (rv == 0)
60 return -EOPNOTSUPP;
61 return rv;
62}
63
64static void ieee80211_get_stats(struct net_device *dev,
65 struct ethtool_stats *stats,
66 u64 *data)
67{
68 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
69 struct ieee80211_chanctx_conf *chanctx_conf;
70 struct ieee80211_channel *channel;
71 struct sta_info *sta;
72 struct ieee80211_local *local = sdata->local;
73 struct station_info sinfo;
74 struct survey_info survey;
75 int i, q;
76#define STA_STATS_SURVEY_LEN 7
77
78 memset(data, 0, sizeof(u64) * STA_STATS_LEN);
79
80#define ADD_STA_STATS(sta) \
81 do { \
82 data[i++] += sta->rx_packets; \
83 data[i++] += sta->rx_bytes; \
84 data[i++] += sta->num_duplicates; \
85 data[i++] += sta->rx_fragments; \
86 data[i++] += sta->rx_dropped; \
87 \
88 data[i++] += sinfo.tx_packets; \
89 data[i++] += sinfo.tx_bytes; \
90 data[i++] += sta->tx_fragments; \
91 data[i++] += sta->tx_filtered_count; \
92 data[i++] += sta->tx_retry_failed; \
93 data[i++] += sta->tx_retry_count; \
94 data[i++] += sta->beacon_loss_count; \
95 } while (0)
96
97 /* For Managed stations, find the single station based on BSSID
98 * and use that. For interface types, iterate through all available
99 * stations and add stats for any station that is assigned to this
100 * network device.
101 */
102
103 mutex_lock(&local->sta_mtx);
104
105 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
106 sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid);
107
108 if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
109 goto do_survey;
110
111 sinfo.filled = 0;
112 sta_set_sinfo(sta, &sinfo);
113
114 i = 0;
115 ADD_STA_STATS(sta);
116
117 data[i++] = sta->sta_state;
118
119
120 if (sinfo.filled & STATION_INFO_TX_BITRATE)
121 data[i] = 100000 *
122 cfg80211_calculate_bitrate(&sinfo.txrate);
123 i++;
124 if (sinfo.filled & STATION_INFO_RX_BITRATE)
125 data[i] = 100000 *
126 cfg80211_calculate_bitrate(&sinfo.rxrate);
127 i++;
128
129 if (sinfo.filled & STATION_INFO_SIGNAL_AVG)
130 data[i] = (u8)sinfo.signal_avg;
131 i++;
132 } else {
133 list_for_each_entry(sta, &local->sta_list, list) {
134 /* Make sure this station belongs to the proper dev */
135 if (sta->sdata->dev != dev)
136 continue;
137
138 sinfo.filled = 0;
139 sta_set_sinfo(sta, &sinfo);
140 i = 0;
141 ADD_STA_STATS(sta);
142 }
143 }
144
145do_survey:
146 i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
147 /* Get survey stats for current channel */
148 survey.filled = 0;
149
150 rcu_read_lock();
151 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
152 if (chanctx_conf)
153 channel = chanctx_conf->def.chan;
154 else
155 channel = NULL;
156 rcu_read_unlock();
157
158 if (channel) {
159 q = 0;
160 do {
161 survey.filled = 0;
162 if (drv_get_survey(local, q, &survey) != 0) {
163 survey.filled = 0;
164 break;
165 }
166 q++;
167 } while (channel != survey.channel);
168 }
169
170 if (survey.filled)
171 data[i++] = survey.channel->center_freq;
172 else
173 data[i++] = 0;
174 if (survey.filled & SURVEY_INFO_NOISE_DBM)
175 data[i++] = (u8)survey.noise;
176 else
177 data[i++] = -1LL;
178 if (survey.filled & SURVEY_INFO_CHANNEL_TIME)
179 data[i++] = survey.channel_time;
180 else
181 data[i++] = -1LL;
182 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
183 data[i++] = survey.channel_time_busy;
184 else
185 data[i++] = -1LL;
186 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
187 data[i++] = survey.channel_time_ext_busy;
188 else
189 data[i++] = -1LL;
190 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX)
191 data[i++] = survey.channel_time_rx;
192 else
193 data[i++] = -1LL;
194 if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX)
195 data[i++] = survey.channel_time_tx;
196 else
197 data[i++] = -1LL;
198
199 mutex_unlock(&local->sta_mtx);
200
201 if (WARN_ON(i != STA_STATS_LEN))
202 return;
203
204 drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
205}
206
207static void ieee80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
208{
209 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
210 int sz_sta_stats = 0;
211
212 if (sset == ETH_SS_STATS) {
213 sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
214 memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats);
215 }
216 drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));
217}
218
219static int ieee80211_get_regs_len(struct net_device *dev)
220{
221 return 0;
222}
223
224static void ieee80211_get_regs(struct net_device *dev,
225 struct ethtool_regs *regs,
226 void *data)
227{
228 struct wireless_dev *wdev = dev->ieee80211_ptr;
229
230 regs->version = wdev->wiphy->hw_version;
231 regs->len = 0;
232}
233
234const struct ethtool_ops ieee80211_ethtool_ops = {
235 .get_drvinfo = cfg80211_get_drvinfo,
236 .get_regs_len = ieee80211_get_regs_len,
237 .get_regs = ieee80211_get_regs,
238 .get_link = ethtool_op_get_link,
239 .get_ringparam = ieee80211_get_ringparam,
240 .set_ringparam = ieee80211_set_ringparam,
241 .get_strings = ieee80211_get_strings,
242 .get_ethtool_stats = ieee80211_get_stats,
243 .get_sset_count = ieee80211_get_sset_count,
244};
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ac9836e0aab3..4372d48b718f 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1847,6 +1847,8 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
1847 const u8 *peer, enum nl80211_tdls_operation oper); 1847 const u8 *peer, enum nl80211_tdls_operation oper);
1848 1848
1849 1849
1850extern const struct ethtool_ops ieee80211_ethtool_ops;
1851
1850#ifdef CONFIG_MAC80211_NOINLINE 1852#ifdef CONFIG_MAC80211_NOINLINE
1851#define debug_noinline noinline 1853#define debug_noinline noinline
1852#else 1854#else
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 388b863e821c..db5afc7faa22 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1705,6 +1705,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1705 1705
1706 ndev->features |= local->hw.netdev_features; 1706 ndev->features |= local->hw.netdev_features;
1707 1707
1708 netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
1709
1708 ret = register_netdevice(ndev); 1710 ret = register_netdevice(ndev);
1709 if (ret) { 1711 if (ret) {
1710 free_netdev(ndev); 1712 free_netdev(ndev);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index ae7c16ad5f22..6fe48f64d0e4 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1719,3 +1719,137 @@ u8 sta_info_tx_streams(struct sta_info *sta)
1719 return ((ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) 1719 return ((ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
1720 >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1; 1720 >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1;
1721} 1721}
1722
1723void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
1724{
1725 struct ieee80211_sub_if_data *sdata = sta->sdata;
1726 struct ieee80211_local *local = sdata->local;
1727 struct rate_control_ref *ref = local->rate_ctrl;
1728 struct timespec uptime;
1729 u64 packets = 0;
1730 u32 thr = 0;
1731 int i, ac;
1732
1733 sinfo->generation = sdata->local->sta_generation;
1734
1735 sinfo->filled = STATION_INFO_INACTIVE_TIME |
1736 STATION_INFO_RX_BYTES64 |
1737 STATION_INFO_TX_BYTES64 |
1738 STATION_INFO_RX_PACKETS |
1739 STATION_INFO_TX_PACKETS |
1740 STATION_INFO_TX_RETRIES |
1741 STATION_INFO_TX_FAILED |
1742 STATION_INFO_TX_BITRATE |
1743 STATION_INFO_RX_BITRATE |
1744 STATION_INFO_RX_DROP_MISC |
1745 STATION_INFO_BSS_PARAM |
1746 STATION_INFO_CONNECTED_TIME |
1747 STATION_INFO_STA_FLAGS |
1748 STATION_INFO_BEACON_LOSS_COUNT;
1749
1750 do_posix_clock_monotonic_gettime(&uptime);
1751 sinfo->connected_time = uptime.tv_sec - sta->last_connected;
1752
1753 sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
1754 sinfo->tx_bytes = 0;
1755 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
1756 sinfo->tx_bytes += sta->tx_bytes[ac];
1757 packets += sta->tx_packets[ac];
1758 }
1759 sinfo->tx_packets = packets;
1760 sinfo->rx_bytes = sta->rx_bytes;
1761 sinfo->rx_packets = sta->rx_packets;
1762 sinfo->tx_retries = sta->tx_retry_count;
1763 sinfo->tx_failed = sta->tx_retry_failed;
1764 sinfo->rx_dropped_misc = sta->rx_dropped;
1765 sinfo->beacon_loss_count = sta->beacon_loss_count;
1766
1767 if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
1768 (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
1769 sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG;
1770 if (!local->ops->get_rssi ||
1771 drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal))
1772 sinfo->signal = (s8)sta->last_signal;
1773 sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
1774 }
1775 if (sta->chains) {
1776 sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
1777 STATION_INFO_CHAIN_SIGNAL_AVG;
1778
1779 sinfo->chains = sta->chains;
1780 for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
1781 sinfo->chain_signal[i] = sta->chain_signal_last[i];
1782 sinfo->chain_signal_avg[i] =
1783 (s8) -ewma_read(&sta->chain_signal_avg[i]);
1784 }
1785 }
1786
1787 sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
1788 sta_set_rate_info_rx(sta, &sinfo->rxrate);
1789
1790 if (ieee80211_vif_is_mesh(&sdata->vif)) {
1791#ifdef CONFIG_MAC80211_MESH
1792 sinfo->filled |= STATION_INFO_LLID |
1793 STATION_INFO_PLID |
1794 STATION_INFO_PLINK_STATE |
1795 STATION_INFO_LOCAL_PM |
1796 STATION_INFO_PEER_PM |
1797 STATION_INFO_NONPEER_PM;
1798
1799 sinfo->llid = sta->llid;
1800 sinfo->plid = sta->plid;
1801 sinfo->plink_state = sta->plink_state;
1802 if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
1803 sinfo->filled |= STATION_INFO_T_OFFSET;
1804 sinfo->t_offset = sta->t_offset;
1805 }
1806 sinfo->local_pm = sta->local_pm;
1807 sinfo->peer_pm = sta->peer_pm;
1808 sinfo->nonpeer_pm = sta->nonpeer_pm;
1809#endif
1810 }
1811
1812 sinfo->bss_param.flags = 0;
1813 if (sdata->vif.bss_conf.use_cts_prot)
1814 sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
1815 if (sdata->vif.bss_conf.use_short_preamble)
1816 sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
1817 if (sdata->vif.bss_conf.use_short_slot)
1818 sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
1819 sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period;
1820 sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int;
1821
1822 sinfo->sta_flags.set = 0;
1823 sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
1824 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
1825 BIT(NL80211_STA_FLAG_WME) |
1826 BIT(NL80211_STA_FLAG_MFP) |
1827 BIT(NL80211_STA_FLAG_AUTHENTICATED) |
1828 BIT(NL80211_STA_FLAG_ASSOCIATED) |
1829 BIT(NL80211_STA_FLAG_TDLS_PEER);
1830 if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
1831 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
1832 if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE))
1833 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
1834 if (test_sta_flag(sta, WLAN_STA_WME))
1835 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME);
1836 if (test_sta_flag(sta, WLAN_STA_MFP))
1837 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP);
1838 if (test_sta_flag(sta, WLAN_STA_AUTH))
1839 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
1840 if (test_sta_flag(sta, WLAN_STA_ASSOC))
1841 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
1842 if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
1843 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
1844
1845 /* check if the driver has a SW RC implementation */
1846 if (ref && ref->ops->get_expected_throughput)
1847 thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
1848 else
1849 thr = drv_get_expected_throughput(local, &sta->sta);
1850
1851 if (thr != 0) {
1852 sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT;
1853 sinfo->expected_throughput = thr;
1854 }
1855}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index fa7ce6f8593b..2a04361b2162 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -627,6 +627,8 @@ void sta_set_rate_info_tx(struct sta_info *sta,
627 struct rate_info *rinfo); 627 struct rate_info *rinfo);
628void sta_set_rate_info_rx(struct sta_info *sta, 628void sta_set_rate_info_rx(struct sta_info *sta,
629 struct rate_info *rinfo); 629 struct rate_info *rinfo);
630void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo);
631
630void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, 632void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
631 unsigned long exp_time); 633 unsigned long exp_time);
632u8 sta_info_tx_streams(struct sta_info *sta); 634u8 sta_info_tx_streams(struct sta_info *sta);