aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c20
-rw-r--r--include/net/mac80211.h17
-rw-r--r--net/mac80211/driver-ops.h30
-rw-r--r--net/mac80211/sta_info.c97
-rw-r--r--net/mac80211/trace.h33
5 files changed, 110 insertions, 87 deletions
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 2a99456b6b8f..8d11b0ca412c 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5376,14 +5376,15 @@ static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw,
5376 wlcore_hw_sta_rc_update(wl, wlvif, sta, changed); 5376 wlcore_hw_sta_rc_update(wl, wlvif, sta, changed);
5377} 5377}
5378 5378
5379static int wlcore_op_get_rssi(struct ieee80211_hw *hw, 5379static void wlcore_op_sta_statistics(struct ieee80211_hw *hw,
5380 struct ieee80211_vif *vif, 5380 struct ieee80211_vif *vif,
5381 struct ieee80211_sta *sta, 5381 struct ieee80211_sta *sta,
5382 s8 *rssi_dbm) 5382 struct station_info *sinfo)
5383{ 5383{
5384 struct wl1271 *wl = hw->priv; 5384 struct wl1271 *wl = hw->priv;
5385 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); 5385 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
5386 int ret = 0; 5386 s8 rssi_dbm;
5387 int ret;
5387 5388
5388 wl1271_debug(DEBUG_MAC80211, "mac80211 get_rssi"); 5389 wl1271_debug(DEBUG_MAC80211, "mac80211 get_rssi");
5389 5390
@@ -5396,17 +5397,18 @@ static int wlcore_op_get_rssi(struct ieee80211_hw *hw,
5396 if (ret < 0) 5397 if (ret < 0)
5397 goto out_sleep; 5398 goto out_sleep;
5398 5399
5399 ret = wlcore_acx_average_rssi(wl, wlvif, rssi_dbm); 5400 ret = wlcore_acx_average_rssi(wl, wlvif, &rssi_dbm);
5400 if (ret < 0) 5401 if (ret < 0)
5401 goto out_sleep; 5402 goto out_sleep;
5402 5403
5404 sinfo->filled |= STATION_INFO_SIGNAL;
5405 sinfo->signal = rssi_dbm;
5406
5403out_sleep: 5407out_sleep:
5404 wl1271_ps_elp_sleep(wl); 5408 wl1271_ps_elp_sleep(wl);
5405 5409
5406out: 5410out:
5407 mutex_unlock(&wl->mutex); 5411 mutex_unlock(&wl->mutex);
5408
5409 return ret;
5410} 5412}
5411 5413
5412static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) 5414static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
@@ -5606,7 +5608,7 @@ static const struct ieee80211_ops wl1271_ops = {
5606 .assign_vif_chanctx = wlcore_op_assign_vif_chanctx, 5608 .assign_vif_chanctx = wlcore_op_assign_vif_chanctx,
5607 .unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx, 5609 .unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx,
5608 .sta_rc_update = wlcore_op_sta_rc_update, 5610 .sta_rc_update = wlcore_op_sta_rc_update,
5609 .get_rssi = wlcore_op_get_rssi, 5611 .sta_statistics = wlcore_op_sta_statistics,
5610 CFG80211_TESTMODE_CMD(wl1271_tm_cmd) 5612 CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
5611}; 5613};
5612 5614
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 555a845ad51e..123f2308958a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2708,6 +2708,14 @@ enum ieee80211_reconfig_type {
2708 * is only used if the configured rate control algorithm actually uses 2708 * is only used if the configured rate control algorithm actually uses
2709 * the new rate table API, and is therefore optional. Must be atomic. 2709 * the new rate table API, and is therefore optional. Must be atomic.
2710 * 2710 *
2711 * @sta_statistics: Get statistics for this station. For example with beacon
2712 * filtering, the statistics kept by mac80211 might not be accurate, so
2713 * let the driver pre-fill the statistics. The driver can fill most of
2714 * the values (indicating which by setting the filled bitmap), but not
2715 * all of them make sense - see the source for which ones are possible.
2716 * Statistics that the driver doesn't fill will be filled by mac80211.
2717 * The callback can sleep.
2718 *
2711 * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), 2719 * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
2712 * bursting) for a hardware TX queue. 2720 * bursting) for a hardware TX queue.
2713 * Returns a negative error code on failure. 2721 * Returns a negative error code on failure.
@@ -2868,9 +2876,6 @@ enum ieee80211_reconfig_type {
2868 * @get_et_strings: Ethtool API to get a set of strings to describe stats 2876 * @get_et_strings: Ethtool API to get a set of strings to describe stats
2869 * and perhaps other supported types of ethtool data-sets. 2877 * and perhaps other supported types of ethtool data-sets.
2870 * 2878 *
2871 * @get_rssi: Get current signal strength in dBm, the function is optional
2872 * and can sleep.
2873 *
2874 * @mgd_prepare_tx: Prepare for transmitting a management frame for association 2879 * @mgd_prepare_tx: Prepare for transmitting a management frame for association
2875 * before associated. In multi-channel scenarios, a virtual interface is 2880 * before associated. In multi-channel scenarios, a virtual interface is
2876 * bound to a channel before it is associated, but as it isn't associated 2881 * bound to a channel before it is associated, but as it isn't associated
@@ -3071,6 +3076,10 @@ struct ieee80211_ops {
3071 void (*sta_rate_tbl_update)(struct ieee80211_hw *hw, 3076 void (*sta_rate_tbl_update)(struct ieee80211_hw *hw,
3072 struct ieee80211_vif *vif, 3077 struct ieee80211_vif *vif,
3073 struct ieee80211_sta *sta); 3078 struct ieee80211_sta *sta);
3079 void (*sta_statistics)(struct ieee80211_hw *hw,
3080 struct ieee80211_vif *vif,
3081 struct ieee80211_sta *sta,
3082 struct station_info *sinfo);
3074 int (*conf_tx)(struct ieee80211_hw *hw, 3083 int (*conf_tx)(struct ieee80211_hw *hw,
3075 struct ieee80211_vif *vif, u16 ac, 3084 struct ieee80211_vif *vif, u16 ac,
3076 const struct ieee80211_tx_queue_params *params); 3085 const struct ieee80211_tx_queue_params *params);
@@ -3138,8 +3147,6 @@ struct ieee80211_ops {
3138 void (*get_et_strings)(struct ieee80211_hw *hw, 3147 void (*get_et_strings)(struct ieee80211_hw *hw,
3139 struct ieee80211_vif *vif, 3148 struct ieee80211_vif *vif,
3140 u32 sset, u8 *data); 3149 u32 sset, u8 *data);
3141 int (*get_rssi)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
3142 struct ieee80211_sta *sta, s8 *rssi_dbm);
3143 3150
3144 void (*mgd_prepare_tx)(struct ieee80211_hw *hw, 3151 void (*mgd_prepare_tx)(struct ieee80211_hw *hw,
3145 struct ieee80211_vif *vif); 3152 struct ieee80211_vif *vif);
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),