aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2014-11-17 05:35:23 -0500
committerJohannes Berg <johannes.berg@intel.com>2015-01-08 09:28:06 -0500
commit2b9a7e1bac24df8ddb0713ad1e5807a7243bcab0 (patch)
treef118d24b4a347e52c0a0a9173178efbe850531af /net/mac80211
parent6f7a8d26e2668e00de524d3da0122a4411047dd2 (diff)
mac80211: allow drivers to provide most station statistics
In many cases, drivers can filter things like beacons that will skew statistics reported by mac80211. To get correct statistics in these cases, call drivers to obtain statistics and let them override all values, filling values from mac80211 if the driver didn't provide them. Not all of them make sense for the driver to fill, so some are still always done by mac80211. Note that this doesn't currently allow a driver to say "I know this value is wrong, don't report it at all", or to sum it up with a mac80211 value (as could be useful for "dropped misc"), that can be added if it turns out to be needed. This also gets rid of the get_rssi() method as is can now be implemented using sta_statistics(). Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/driver-ops.h30
-rw-r--r--net/mac80211/sta_info.c97
-rw-r--r--net/mac80211/trace.h33
3 files changed, 87 insertions, 73 deletions
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 2ebc9ead9695..fdeda17b8dd2 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -639,6 +639,21 @@ static inline void drv_sta_rate_tbl_update(struct ieee80211_local *local,
639 trace_drv_return_void(local); 639 trace_drv_return_void(local);
640} 640}
641 641
642static inline void drv_sta_statistics(struct ieee80211_local *local,
643 struct ieee80211_sub_if_data *sdata,
644 struct ieee80211_sta *sta,
645 struct station_info *sinfo)
646{
647 sdata = get_bss_sdata(sdata);
648 if (!check_sdata_in_driver(sdata))
649 return;
650
651 trace_drv_sta_statistics(local, sdata, sta);
652 if (local->ops->sta_statistics)
653 local->ops->sta_statistics(&local->hw, &sdata->vif, sta, sinfo);
654 trace_drv_return_void(local);
655}
656
642static inline int drv_conf_tx(struct ieee80211_local *local, 657static inline int drv_conf_tx(struct ieee80211_local *local,
643 struct ieee80211_sub_if_data *sdata, u16 ac, 658 struct ieee80211_sub_if_data *sdata, u16 ac,
644 const struct ieee80211_tx_queue_params *params) 659 const struct ieee80211_tx_queue_params *params)
@@ -966,21 +981,6 @@ drv_allow_buffered_frames(struct ieee80211_local *local,
966 trace_drv_return_void(local); 981 trace_drv_return_void(local);
967} 982}
968 983
969static inline int drv_get_rssi(struct ieee80211_local *local,
970 struct ieee80211_sub_if_data *sdata,
971 struct ieee80211_sta *sta,
972 s8 *rssi_dbm)
973{
974 int ret;
975
976 might_sleep();
977
978 ret = local->ops->get_rssi(&local->hw, &sdata->vif, sta, rssi_dbm);
979 trace_drv_get_rssi(local, sta, *rssi_dbm, ret);
980
981 return ret;
982}
983
984static inline void drv_mgd_prepare_tx(struct ieee80211_local *local, 984static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,
985 struct ieee80211_sub_if_data *sdata) 985 struct ieee80211_sub_if_data *sdata)
986{ 986{
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 388ff0b2ad2b..967b42eae5c2 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1746,7 +1746,6 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
1746 struct ieee80211_local *local = sdata->local; 1746 struct ieee80211_local *local = sdata->local;
1747 struct rate_control_ref *ref = NULL; 1747 struct rate_control_ref *ref = NULL;
1748 struct timespec uptime; 1748 struct timespec uptime;
1749 u64 packets = 0;
1750 u32 thr = 0; 1749 u32 thr = 0;
1751 int i, ac; 1750 int i, ac;
1752 1751
@@ -1755,47 +1754,74 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
1755 1754
1756 sinfo->generation = sdata->local->sta_generation; 1755 sinfo->generation = sdata->local->sta_generation;
1757 1756
1758 sinfo->filled = STATION_INFO_INACTIVE_TIME | 1757 drv_sta_statistics(local, sdata, &sta->sta, sinfo);
1759 STATION_INFO_RX_BYTES64 | 1758
1760 STATION_INFO_TX_BYTES64 | 1759 sinfo->filled |= STATION_INFO_INACTIVE_TIME |
1761 STATION_INFO_RX_PACKETS | 1760 STATION_INFO_STA_FLAGS |
1762 STATION_INFO_TX_PACKETS | 1761 STATION_INFO_BSS_PARAM |
1763 STATION_INFO_TX_RETRIES | 1762 STATION_INFO_CONNECTED_TIME |
1764 STATION_INFO_TX_FAILED | 1763 STATION_INFO_RX_DROP_MISC |
1765 STATION_INFO_TX_BITRATE | 1764 STATION_INFO_BEACON_LOSS_COUNT;
1766 STATION_INFO_RX_BITRATE |
1767 STATION_INFO_RX_DROP_MISC |
1768 STATION_INFO_BSS_PARAM |
1769 STATION_INFO_CONNECTED_TIME |
1770 STATION_INFO_STA_FLAGS |
1771 STATION_INFO_BEACON_LOSS_COUNT;
1772 1765
1773 ktime_get_ts(&uptime); 1766 ktime_get_ts(&uptime);
1774 sinfo->connected_time = uptime.tv_sec - sta->last_connected; 1767 sinfo->connected_time = uptime.tv_sec - sta->last_connected;
1775
1776 sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); 1768 sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
1777 sinfo->tx_bytes = 0; 1769
1778 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { 1770 if (!(sinfo->filled & (STATION_INFO_TX_BYTES64 |
1779 sinfo->tx_bytes += sta->tx_bytes[ac]; 1771 STATION_INFO_TX_BYTES))) {
1780 packets += sta->tx_packets[ac]; 1772 sinfo->tx_bytes = 0;
1773 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
1774 sinfo->tx_bytes += sta->tx_bytes[ac];
1775 sinfo->filled |= STATION_INFO_TX_BYTES64;
1776 }
1777
1778 if (!(sinfo->filled & STATION_INFO_TX_PACKETS)) {
1779 sinfo->tx_packets = 0;
1780 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
1781 sinfo->tx_packets += sta->tx_packets[ac];
1782 sinfo->filled |= STATION_INFO_TX_PACKETS;
1783 }
1784
1785 if (!(sinfo->filled & (STATION_INFO_RX_BYTES64 |
1786 STATION_INFO_RX_BYTES))) {
1787 sinfo->rx_bytes = sta->rx_bytes;
1788 sinfo->filled |= STATION_INFO_RX_BYTES64;
1789 }
1790
1791 if (!(sinfo->filled & STATION_INFO_RX_PACKETS)) {
1792 sinfo->rx_packets = sta->rx_packets;
1793 sinfo->filled |= STATION_INFO_RX_PACKETS;
1794 }
1795
1796 if (!(sinfo->filled & STATION_INFO_TX_RETRIES)) {
1797 sinfo->tx_retries = sta->tx_retry_count;
1798 sinfo->filled |= STATION_INFO_TX_RETRIES;
1799 }
1800
1801 if (!(sinfo->filled & STATION_INFO_TX_FAILED)) {
1802 sinfo->tx_failed = sta->tx_retry_failed;
1803 sinfo->filled |= STATION_INFO_TX_FAILED;
1781 } 1804 }
1782 sinfo->tx_packets = packets; 1805
1783 sinfo->rx_bytes = sta->rx_bytes;
1784 sinfo->rx_packets = sta->rx_packets;
1785 sinfo->tx_retries = sta->tx_retry_count;
1786 sinfo->tx_failed = sta->tx_retry_failed;
1787 sinfo->rx_dropped_misc = sta->rx_dropped; 1806 sinfo->rx_dropped_misc = sta->rx_dropped;
1788 sinfo->beacon_loss_count = sta->beacon_loss_count; 1807 sinfo->beacon_loss_count = sta->beacon_loss_count;
1789 1808
1790 if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || 1809 if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
1791 (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { 1810 (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
1792 sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG; 1811 if (!(sinfo->filled & STATION_INFO_SIGNAL)) {
1793 if (!local->ops->get_rssi ||
1794 drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal))
1795 sinfo->signal = (s8)sta->last_signal; 1812 sinfo->signal = (s8)sta->last_signal;
1796 sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal); 1813 sinfo->filled |= STATION_INFO_SIGNAL;
1814 }
1815
1816 if (!(sinfo->filled & STATION_INFO_SIGNAL_AVG)) {
1817 sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
1818 sinfo->filled |= STATION_INFO_SIGNAL_AVG;
1819 }
1797 } 1820 }
1798 if (sta->chains) { 1821
1822 if (sta->chains &&
1823 !(sinfo->filled & (STATION_INFO_CHAIN_SIGNAL |
1824 STATION_INFO_CHAIN_SIGNAL_AVG))) {
1799 sinfo->filled |= STATION_INFO_CHAIN_SIGNAL | 1825 sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
1800 STATION_INFO_CHAIN_SIGNAL_AVG; 1826 STATION_INFO_CHAIN_SIGNAL_AVG;
1801 1827
@@ -1807,8 +1833,15 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
1807 } 1833 }
1808 } 1834 }
1809 1835
1810 sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); 1836 if (!(sinfo->filled & STATION_INFO_TX_BITRATE)) {
1811 sta_set_rate_info_rx(sta, &sinfo->rxrate); 1837 sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
1838 sinfo->filled |= STATION_INFO_TX_BITRATE;
1839 }
1840
1841 if (!(sinfo->filled & STATION_INFO_RX_BITRATE)) {
1842 sta_set_rate_info_rx(sta, &sinfo->rxrate);
1843 sinfo->filled |= STATION_INFO_RX_BITRATE;
1844 }
1812 1845
1813 if (ieee80211_vif_is_mesh(&sdata->vif)) { 1846 if (ieee80211_vif_is_mesh(&sdata->vif)) {
1814#ifdef CONFIG_MAC80211_MESH 1847#ifdef CONFIG_MAC80211_MESH
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 8e461a02c6a8..263a9561eb26 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -825,6 +825,13 @@ DECLARE_EVENT_CLASS(sta_event,
825 ) 825 )
826); 826);
827 827
828DEFINE_EVENT(sta_event, drv_sta_statistics,
829 TP_PROTO(struct ieee80211_local *local,
830 struct ieee80211_sub_if_data *sdata,
831 struct ieee80211_sta *sta),
832 TP_ARGS(local, sdata, sta)
833);
834
828DEFINE_EVENT(sta_event, drv_sta_add, 835DEFINE_EVENT(sta_event, drv_sta_add,
829 TP_PROTO(struct ieee80211_local *local, 836 TP_PROTO(struct ieee80211_local *local,
830 struct ieee80211_sub_if_data *sdata, 837 struct ieee80211_sub_if_data *sdata,
@@ -1329,32 +1336,6 @@ DEFINE_EVENT(release_evt, drv_allow_buffered_frames,
1329 TP_ARGS(local, sta, tids, num_frames, reason, more_data) 1336 TP_ARGS(local, sta, tids, num_frames, reason, more_data)
1330); 1337);
1331 1338
1332TRACE_EVENT(drv_get_rssi,
1333 TP_PROTO(struct ieee80211_local *local, struct ieee80211_sta *sta,
1334 s8 rssi, int ret),
1335
1336 TP_ARGS(local, sta, rssi, ret),
1337
1338 TP_STRUCT__entry(
1339 LOCAL_ENTRY
1340 STA_ENTRY
1341 __field(s8, rssi)
1342 __field(int, ret)
1343 ),
1344
1345 TP_fast_assign(
1346 LOCAL_ASSIGN;
1347 STA_ASSIGN;
1348 __entry->rssi = rssi;
1349 __entry->ret = ret;
1350 ),
1351
1352 TP_printk(
1353 LOCAL_PR_FMT STA_PR_FMT " rssi:%d ret:%d",
1354 LOCAL_PR_ARG, STA_PR_ARG, __entry->rssi, __entry->ret
1355 )
1356);
1357
1358DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx, 1339DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx,
1359 TP_PROTO(struct ieee80211_local *local, 1340 TP_PROTO(struct ieee80211_local *local,
1360 struct ieee80211_sub_if_data *sdata), 1341 struct ieee80211_sub_if_data *sdata),