Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next

This commit is contained in:
David S. Miller
2012-05-14 18:00:48 -04:00
43 changed files with 902 additions and 253 deletions

View File

@@ -450,6 +450,180 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
}
static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
"rx_packets", "rx_bytes", "wep_weak_iv_count",
"rx_duplicates", "rx_fragments", "rx_dropped",
"tx_packets", "tx_bytes", "tx_fragments",
"tx_filtered", "tx_retry_failed", "tx_retries",
"beacon_loss", "sta_state", "txrate", "rxrate", "signal",
"channel", "noise", "ch_time", "ch_time_busy",
"ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
};
#define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats)
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)
rv += STA_STATS_LEN;
rv += drv_get_et_sset_count(sdata, sset);
if (rv == 0)
return -EOPNOTSUPP;
return rv;
}
static void ieee80211_get_et_stats(struct wiphy *wiphy,
struct net_device *dev,
struct ethtool_stats *stats,
u64 *data)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct sta_info *sta;
struct ieee80211_local *local = sdata->local;
struct station_info sinfo;
struct survey_info survey;
int i, q;
#define STA_STATS_SURVEY_LEN 7
memset(data, 0, sizeof(u64) * STA_STATS_LEN);
#define ADD_STA_STATS(sta) \
do { \
data[i++] += sta->rx_packets; \
data[i++] += sta->rx_bytes; \
data[i++] += sta->wep_weak_iv_count; \
data[i++] += sta->num_duplicates; \
data[i++] += sta->rx_fragments; \
data[i++] += sta->rx_dropped; \
\
data[i++] += sta->tx_packets; \
data[i++] += sta->tx_bytes; \
data[i++] += sta->tx_fragments; \
data[i++] += sta->tx_filtered_count; \
data[i++] += sta->tx_retry_failed; \
data[i++] += sta->tx_retry_count; \
data[i++] += sta->beacon_loss_count; \
} while (0)
/* For Managed stations, find the single station based on BSSID
* and use that. For interface types, iterate through all available
* stations and add stats for any station that is assigned to this
* network device.
*/
rcu_read_lock();
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid);
if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
goto do_survey;
i = 0;
ADD_STA_STATS(sta);
data[i++] = sta->sta_state;
sinfo.filled = 0;
sta_set_sinfo(sta, &sinfo);
if (sinfo.filled | STATION_INFO_TX_BITRATE)
data[i] = 100000 *
cfg80211_calculate_bitrate(&sinfo.txrate);
i++;
if (sinfo.filled | STATION_INFO_RX_BITRATE)
data[i] = 100000 *
cfg80211_calculate_bitrate(&sinfo.rxrate);
i++;
if (sinfo.filled | STATION_INFO_SIGNAL_AVG)
data[i] = (u8)sinfo.signal_avg;
i++;
} else {
list_for_each_entry_rcu(sta, &local->sta_list, list) {
/* Make sure this station belongs to the proper dev */
if (sta->sdata->dev != dev)
continue;
i = 0;
ADD_STA_STATS(sta);
}
}
do_survey:
i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
/* Get survey stats for current channel */
q = 0;
while (true) {
survey.filled = 0;
if (drv_get_survey(local, q, &survey) != 0) {
survey.filled = 0;
break;
}
if (survey.channel &&
(local->oper_channel->center_freq ==
survey.channel->center_freq))
break;
q++;
}
if (survey.filled)
data[i++] = survey.channel->center_freq;
else
data[i++] = 0;
if (survey.filled & SURVEY_INFO_NOISE_DBM)
data[i++] = (u8)survey.noise;
else
data[i++] = -1LL;
if (survey.filled & SURVEY_INFO_CHANNEL_TIME)
data[i++] = survey.channel_time;
else
data[i++] = -1LL;
if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
data[i++] = survey.channel_time_busy;
else
data[i++] = -1LL;
if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
data[i++] = survey.channel_time_ext_busy;
else
data[i++] = -1LL;
if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX)
data[i++] = survey.channel_time_rx;
else
data[i++] = -1LL;
if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX)
data[i++] = survey.channel_time_tx;
else
data[i++] = -1LL;
rcu_read_unlock();
if (WARN_ON(i != STA_STATS_LEN))
return;
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) {
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,
int idx, u8 *mac, struct station_info *sinfo)
@@ -1364,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;
}
@@ -2794,4 +2973,7 @@ struct cfg80211_ops mac80211_config_ops = {
#ifdef CONFIG_PM
.set_wakeup = ieee80211_set_wakeup,
#endif
.get_et_sset_count = ieee80211_get_et_sset_count,
.get_et_stats = ieee80211_get_et_stats,
.get_et_strings = ieee80211_get_et_strings,
};