From d61992182e41e1beec0507fd7bce4ba1face12d6 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Mon, 23 Apr 2012 12:50:29 -0700 Subject: cfg80211: Add framework to support ethtool stats. Signed-off-by: Ben Greear Signed-off-by: John W. Linville --- include/net/cfg80211.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'include/net') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 815dc3f37e2b..27f956101bbd 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1514,6 +1514,16 @@ struct cfg80211_gtk_rekey_data { * later passes to cfg80211_probe_status(). * * @set_noack_map: Set the NoAck Map for the TIDs. + * + * @get_et_sset_count: Ethtool API to get string-set count. + * See @ethtool_ops.get_sset_count + * + * @get_et_stats: Ethtool API to get a set of u64 stats. + * See @ethtool_ops.get_ethtool_stats + * + * @get_et_strings: Ethtool API to get a set of strings to describe stats + * and perhaps other supported types of ethtool data-sets. + * See @ethtool_ops.get_strings */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); @@ -1712,6 +1722,13 @@ struct cfg80211_ops { struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy, enum nl80211_channel_type *type); + + int (*get_et_sset_count)(struct wiphy *wiphy, + struct net_device *dev, int sset); + void (*get_et_stats)(struct wiphy *wiphy, struct net_device *dev, + struct ethtool_stats *stats, u64 *data); + void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev, + u32 sset, u8 *data); }; /* -- cgit v1.2.3 From e352114fd62f6d568ca0cb18f589cb8df710cf02 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Mon, 23 Apr 2012 12:50:31 -0700 Subject: mac80211: Framework to get wifi-driver stats via ethtool. This adds hooks to call into the driver to get additional stats for the ethtool API. Signed-off-by: Ben Greear Signed-off-by: John W. Linville --- include/net/mac80211.h | 17 +++++++++++++++++ net/mac80211/cfg.c | 19 ++++++++++++++++--- net/mac80211/driver-ops.h | 37 +++++++++++++++++++++++++++++++++++++ net/mac80211/driver-trace.h | 15 +++++++++++++++ 4 files changed, 85 insertions(+), 3 deletions(-) (limited to 'include/net') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index da3658177997..4d6e6c6818d0 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -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); }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 31023ca17575..a38b26730652 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -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, diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 4a0e559cb26b..6d33a0c743ab 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -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; diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 7c0754bed61b..6de00b2c268c 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -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) -- cgit v1.2.3 From 70c33eaae79e53f9e48324736c0cb85534d3f093 Mon Sep 17 00:00:00 2001 From: Ashok Nagarajan Date: Mon, 30 Apr 2012 14:20:32 -0700 Subject: {nl,cfg,mac}80211: Allow user to see/configure HT protection mode This patch introduces a new mesh configuration parameter "ht_opmode" and will allow user to check the current HT protection mode selected. Users could configure the protection mode by the command "iw mesh_iface set mesh_param mesh_ht_protection_mode=2". The default protection mode of mesh is set to non-HT mixed mode. Signed-off-by: Ashok Nagarajan Reviewed-by: Thomas Pedersen Signed-off-by: John W. Linville --- include/linux/nl80211.h | 3 +++ include/net/cfg80211.h | 1 + net/mac80211/cfg.c | 5 +++++ net/mac80211/mesh.c | 3 +++ net/mac80211/mesh_plink.c | 1 + net/wireless/mesh.c | 1 + net/wireless/nl80211.c | 7 ++++++- 7 files changed, 20 insertions(+), 1 deletion(-) (limited to 'include/net') diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 1335084b1c69..2540e86d99ab 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -2154,6 +2154,8 @@ enum nl80211_mntr_flags { * @NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR: maximum number of neighbors * to synchronize to for 11s default synchronization method (see 11C.12.2.2) * + * @NL80211_MESHCONF_HT_OPMODE: set mesh HT protection mode. + * * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use */ enum nl80211_meshconf_params { @@ -2179,6 +2181,7 @@ enum nl80211_meshconf_params { NL80211_MESHCONF_FORWARDING, NL80211_MESHCONF_RSSI_THRESHOLD, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, + NL80211_MESHCONF_HT_OPMODE, /* keep last */ __NL80211_MESHCONF_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 27f956101bbd..adb2320bccdf 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -821,6 +821,7 @@ struct mesh_config { bool dot11MeshGateAnnouncementProtocol; bool dot11MeshForwarding; s32 rssi_threshold; + u16 ht_opmode; }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 39b1fffb24f4..0221270c0ddf 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1538,6 +1538,11 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, return -ENOTSUPP; conf->rssi_threshold = nconf->rssi_threshold; } + if (_chg_mesh_attr(NL80211_MESHCONF_HT_OPMODE, mask)) { + conf->ht_opmode = nconf->ht_opmode; + sdata->vif.bss_conf.ht_operation_mode = nconf->ht_opmode; + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); + } return 0; } diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 0fabb8bae9fb..0a21e4e55f43 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -595,12 +595,15 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); ieee80211_mesh_root_setup(ifmsh); ieee80211_queue_work(&local->hw, &sdata->work); + sdata->vif.bss_conf.ht_operation_mode = + ifmsh->mshcfg.ht_opmode; sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; sdata->vif.bss_conf.basic_rates = ieee80211_mandatory_rates(sdata->local, sdata->local->hw.conf.channel->band); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED | + BSS_CHANGED_HT | BSS_CHANGED_BASIC_RATES | BSS_CHANGED_BEACON_INT); } diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 2e0ae7310697..8cc8461b48a0 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -157,6 +157,7 @@ out: if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) { sdata->vif.bss_conf.ht_operation_mode = ht_opmode; + sdata->u.mesh.mshcfg.ht_opmode = ht_opmode; changed = BSS_CHANGED_HT; mpl_dbg("mesh_plink %pM: protection mode changed to %d", sdata->vif.addr, ht_opmode); diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 8c747fa9319b..2749cb86b462 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -61,6 +61,7 @@ const struct mesh_config default_mesh_config = { .dot11MeshGateAnnouncementProtocol = false, .dot11MeshForwarding = true, .rssi_threshold = MESH_RSSI_THRESHOLD, + .ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED, }; const struct mesh_setup default_mesh_setup = { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d5005c59c472..b67b1114e25a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3390,7 +3390,9 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, nla_put_u8(msg, NL80211_MESHCONF_FORWARDING, cur_params.dot11MeshForwarding) || nla_put_u32(msg, NL80211_MESHCONF_RSSI_THRESHOLD, - cur_params.rssi_threshold)) + cur_params.rssi_threshold) || + nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE, + cur_params.ht_opmode)) goto nla_put_failure; nla_nest_end(msg, pinfoattr); genlmsg_end(msg, hdr); @@ -3426,6 +3428,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 }, [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 }, [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32}, + [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16}, }; static const struct nla_policy @@ -3523,6 +3526,8 @@ do {\ mask, NL80211_MESHCONF_FORWARDING, nla_get_u8); FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, mask, NL80211_MESHCONF_RSSI_THRESHOLD, nla_get_u32); + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, + mask, NL80211_MESHCONF_HT_OPMODE, nla_get_u16); if (mask_out) *mask_out = mask; -- cgit v1.2.3