summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h1
-rw-r--r--net/mac80211/wext.c69
-rw-r--r--net/wireless/wext-compat.c59
3 files changed, 61 insertions, 68 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 579085564883..fe87819954a5 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1646,6 +1646,7 @@ int cfg80211_wext_siwtxpower(struct net_device *dev,
1646int cfg80211_wext_giwtxpower(struct net_device *dev, 1646int cfg80211_wext_giwtxpower(struct net_device *dev,
1647 struct iw_request_info *info, 1647 struct iw_request_info *info,
1648 union iwreq_data *data, char *keybuf); 1648 union iwreq_data *data, char *keybuf);
1649struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev);
1649 1650
1650int cfg80211_wext_siwpower(struct net_device *dev, 1651int cfg80211_wext_siwpower(struct net_device *dev,
1651 struct iw_request_info *info, 1652 struct iw_request_info *info,
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 244d830f5cfb..5acb8140ee58 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -165,73 +165,6 @@ static int ieee80211_ioctl_giwap(struct net_device *dev,
165} 165}
166 166
167 167
168/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
169static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
170{
171 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
172 struct iw_statistics *wstats = &local->wstats;
173 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
174 struct sta_info *sta = NULL;
175
176 rcu_read_lock();
177
178 if (sdata->vif.type == NL80211_IFTYPE_STATION)
179 sta = sta_info_get(local, sdata->u.mgd.bssid);
180
181 if (!sta) {
182 wstats->discard.fragment = 0;
183 wstats->discard.misc = 0;
184 wstats->qual.qual = 0;
185 wstats->qual.level = 0;
186 wstats->qual.noise = 0;
187 wstats->qual.updated = IW_QUAL_ALL_INVALID;
188 } else {
189 wstats->qual.updated = 0;
190 /*
191 * mirror what cfg80211 does for iwrange/scan results,
192 * otherwise userspace gets confused.
193 */
194 if (local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC |
195 IEEE80211_HW_SIGNAL_DBM)) {
196 wstats->qual.updated |= IW_QUAL_LEVEL_UPDATED;
197 wstats->qual.updated |= IW_QUAL_QUAL_UPDATED;
198 } else {
199 wstats->qual.updated |= IW_QUAL_LEVEL_INVALID;
200 wstats->qual.updated |= IW_QUAL_QUAL_INVALID;
201 }
202
203 if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) {
204 wstats->qual.level = sta->last_signal;
205 wstats->qual.qual = sta->last_signal;
206 } else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
207 int sig = sta->last_signal;
208
209 wstats->qual.updated |= IW_QUAL_DBM;
210 wstats->qual.level = sig;
211 if (sig < -110)
212 sig = -110;
213 else if (sig > -40)
214 sig = -40;
215 wstats->qual.qual = sig + 110;
216 }
217
218 if (local->hw.flags & IEEE80211_HW_NOISE_DBM) {
219 /*
220 * This assumes that if driver reports noise, it also
221 * reports signal in dBm.
222 */
223 wstats->qual.noise = sta->last_noise;
224 wstats->qual.updated |= IW_QUAL_NOISE_UPDATED;
225 } else {
226 wstats->qual.updated |= IW_QUAL_NOISE_INVALID;
227 }
228 }
229
230 rcu_read_unlock();
231
232 return wstats;
233}
234
235/* Structures to export the Wireless Handlers */ 168/* Structures to export the Wireless Handlers */
236 169
237static const iw_handler ieee80211_handler[] = 170static const iw_handler ieee80211_handler[] =
@@ -298,5 +231,5 @@ const struct iw_handler_def ieee80211_iw_handler_def =
298{ 231{
299 .num_standard = ARRAY_SIZE(ieee80211_handler), 232 .num_standard = ARRAY_SIZE(ieee80211_handler),
300 .standard = (iw_handler *) ieee80211_handler, 233 .standard = (iw_handler *) ieee80211_handler,
301 .get_wireless_stats = ieee80211_get_wireless_stats, 234 .get_wireless_stats = cfg80211_wireless_stats,
302}; 235};
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 3a5f999703f1..226cf8609079 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -1156,3 +1156,62 @@ int cfg80211_wext_giwrate(struct net_device *dev,
1156 return 0; 1156 return 0;
1157} 1157}
1158EXPORT_SYMBOL_GPL(cfg80211_wext_giwrate); 1158EXPORT_SYMBOL_GPL(cfg80211_wext_giwrate);
1159
1160/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
1161struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
1162{
1163 struct wireless_dev *wdev = dev->ieee80211_ptr;
1164 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1165 /* we are under RTNL - globally locked - so can use static structs */
1166 static struct iw_statistics wstats;
1167 static struct station_info sinfo;
1168 u8 *addr;
1169
1170 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)
1171 return NULL;
1172
1173 if (!rdev->ops->get_station)
1174 return NULL;
1175
1176 addr = wdev->wext.connect.bssid;
1177 if (!addr)
1178 return NULL;
1179
1180 if (rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo))
1181 return NULL;
1182
1183 memset(&wstats, 0, sizeof(wstats));
1184
1185 switch (rdev->wiphy.signal_type) {
1186 case CFG80211_SIGNAL_TYPE_MBM:
1187 if (sinfo.filled & STATION_INFO_SIGNAL) {
1188 int sig = sinfo.signal;
1189 wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
1190 wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
1191 wstats.qual.updated |= IW_QUAL_DBM;
1192 wstats.qual.level = sig;
1193 if (sig < -110)
1194 sig = -110;
1195 else if (sig > -40)
1196 sig = -40;
1197 wstats.qual.qual = sig + 110;
1198 break;
1199 }
1200 case CFG80211_SIGNAL_TYPE_UNSPEC:
1201 if (sinfo.filled & STATION_INFO_SIGNAL) {
1202 wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
1203 wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
1204 wstats.qual.level = sinfo.signal;
1205 wstats.qual.qual = sinfo.signal;
1206 break;
1207 }
1208 default:
1209 wstats.qual.updated |= IW_QUAL_LEVEL_INVALID;
1210 wstats.qual.updated |= IW_QUAL_QUAL_INVALID;
1211 }
1212
1213 wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
1214
1215 return &wstats;
1216}
1217EXPORT_SYMBOL_GPL(cfg80211_wireless_stats);