mac80211: Framework to get wifi-driver stats via ethtool.
authorBen Greear <greearb@candelatech.com>
Mon, 23 Apr 2012 19:50:31 +0000 (12:50 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 9 May 2012 01:53:51 +0000 (21:53 -0400)
This adds hooks to call into the driver to get additional
stats for the ethtool API.

Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/net/mac80211.h
net/mac80211/cfg.c
net/mac80211/driver-ops.h
net/mac80211/driver-trace.h

index da36581..4d6e6c6 100644 (file)
@@ -2223,6 +2223,14 @@ enum ieee80211_rate_control_changed {
  *     The @tids parameter is a bitmap and tells the driver which TIDs the
  *     frames will be on; it will at most have two bits set.
  *     This callback must be atomic.
+ *
+ * @get_et_sset_count:  Ethtool API to get string-set count.
+ *
+ * @get_et_stats:  Ethtool API to get a set of u64 stats.
+ *
+ * @get_et_strings:  Ethtool API to get a set of strings to describe stats
+ *     and perhaps other supported types of ethtool data-sets.
+ *
  */
 struct ieee80211_ops {
        void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -2353,6 +2361,15 @@ struct ieee80211_ops {
                                        u16 tids, int num_frames,
                                        enum ieee80211_frame_release_type reason,
                                        bool more_data);
+
+       int     (*get_et_sset_count)(struct ieee80211_hw *hw,
+                                    struct ieee80211_vif *vif, int sset);
+       void    (*get_et_stats)(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif,
+                               struct ethtool_stats *stats, u64 *data);
+       void    (*get_et_strings)(struct ieee80211_hw *hw,
+                                 struct ieee80211_vif *vif,
+                                 u32 sset, u8 *data);
 };
 
 /**
index 31023ca..a38b267 100644 (file)
@@ -463,10 +463,17 @@ static int ieee80211_get_et_sset_count(struct wiphy *wiphy,
                                       struct net_device *dev,
                                       int sset)
 {
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       int rv = 0;
+
        if (sset == ETH_SS_STATS)
-               return STA_STATS_LEN;
+               rv += STA_STATS_LEN;
 
-       return -EOPNOTSUPP;
+       rv += drv_get_et_sset_count(sdata, sset);
+
+       if (rv == 0)
+               return -EOPNOTSUPP;
+       return rv;
 }
 
 static void ieee80211_get_et_stats(struct wiphy *wiphy,
@@ -527,16 +534,22 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
        }
 
        rcu_read_unlock();
+
+       drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
 }
 
 static void ieee80211_get_et_strings(struct wiphy *wiphy,
                                     struct net_device *dev,
                                     u32 sset, u8 *data)
 {
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       int sz_sta_stats = 0;
+
        if (sset == ETH_SS_STATS) {
-               int sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
+               sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
                memcpy(data, *ieee80211_gstrings_sta_stats, sz_sta_stats);
        }
+       drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));
 }
 
 static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
index 4a0e559..6d33a0c 100644 (file)
@@ -35,6 +35,43 @@ static inline void drv_tx_frags(struct ieee80211_local *local,
        local->ops->tx_frags(&local->hw, vif, sta, skbs);
 }
 
+static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata,
+                                     u32 sset, u8 *data)
+{
+       struct ieee80211_local *local = sdata->local;
+       if (local->ops->get_et_strings) {
+               trace_drv_get_et_strings(local, sset);
+               local->ops->get_et_strings(&local->hw, &sdata->vif, sset, data);
+               trace_drv_return_void(local);
+       }
+}
+
+static inline void drv_get_et_stats(struct ieee80211_sub_if_data *sdata,
+                                   struct ethtool_stats *stats,
+                                   u64 *data)
+{
+       struct ieee80211_local *local = sdata->local;
+       if (local->ops->get_et_stats) {
+               trace_drv_get_et_stats(local);
+               local->ops->get_et_stats(&local->hw, &sdata->vif, stats, data);
+               trace_drv_return_void(local);
+       }
+}
+
+static inline int drv_get_et_sset_count(struct ieee80211_sub_if_data *sdata,
+                                       int sset)
+{
+       struct ieee80211_local *local = sdata->local;
+       int rv = 0;
+       if (local->ops->get_et_sset_count) {
+               trace_drv_get_et_sset_count(local, sset);
+               rv = local->ops->get_et_sset_count(&local->hw, &sdata->vif,
+                                                  sset);
+               trace_drv_return_int(local, rv);
+       }
+       return rv;
+}
+
 static inline int drv_start(struct ieee80211_local *local)
 {
        int ret;
index 7c0754b..6de00b2 100644 (file)
@@ -161,6 +161,21 @@ DEFINE_EVENT(local_only_evt, drv_start,
        TP_ARGS(local)
 );
 
+DEFINE_EVENT(local_u32_evt, drv_get_et_strings,
+            TP_PROTO(struct ieee80211_local *local, u32 sset),
+            TP_ARGS(local, sset)
+);
+
+DEFINE_EVENT(local_u32_evt, drv_get_et_sset_count,
+            TP_PROTO(struct ieee80211_local *local, u32 sset),
+            TP_ARGS(local, sset)
+);
+
+DEFINE_EVENT(local_only_evt, drv_get_et_stats,
+            TP_PROTO(struct ieee80211_local *local),
+            TP_ARGS(local)
+);
+
 DEFINE_EVENT(local_only_evt, drv_suspend,
        TP_PROTO(struct ieee80211_local *local),
        TP_ARGS(local)