aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntonio Quartulli <antonio@open-mesh.com>2014-05-19 15:53:20 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-05-21 03:15:16 -0400
commitcca674d47e59665630f3005291b61bb883015fc5 (patch)
treebd83cc2c0b576cdc7adae72ca7c170c1e1648fa8
parent867d849fc844623a88ec7b380442952b5ffe5e68 (diff)
mac80211: export the expected throughput
Add get_expected_throughput() API to mac80211 so that each driver can implement its own version based on the RC algorithm they are using (might be using an HW RC algo). The API returns a value expressed in Kbps. Also, add the new get_expected_throughput() member to the rate_control_ops structure in order to be able to query the RC algorithm (this patch provides an implementation of this API for both minstrel and minstrel_ht). The related member in the station_info object is now filled accordingly when dumping a station. Cc: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Antonio Quartulli <antonio@open-mesh.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/mac80211.h7
-rw-r--r--net/mac80211/cfg.c13
-rw-r--r--net/mac80211/driver-ops.h13
-rw-r--r--net/mac80211/rc80211_minstrel.c12
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c17
-rw-r--r--net/mac80211/trace.h32
6 files changed, 94 insertions, 0 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a34f26a4ed18..2c78997bc48d 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2769,6 +2769,10 @@ enum ieee80211_roc_type {
2769 * information in bss_conf is set up and the beacon can be retrieved. A 2769 * information in bss_conf is set up and the beacon can be retrieved. A
2770 * channel context is bound before this is called. 2770 * channel context is bound before this is called.
2771 * @leave_ibss: Leave the IBSS again. 2771 * @leave_ibss: Leave the IBSS again.
2772 *
2773 * @get_expected_throughput: extract the expected throughput towards the
2774 * specified station. The returned value is expressed in Kbps. It returns 0
2775 * if the RC algorithm does not have proper data to provide.
2772 */ 2776 */
2773struct ieee80211_ops { 2777struct ieee80211_ops {
2774 void (*tx)(struct ieee80211_hw *hw, 2778 void (*tx)(struct ieee80211_hw *hw,
@@ -2962,6 +2966,7 @@ struct ieee80211_ops {
2962 2966
2963 int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); 2967 int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
2964 void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); 2968 void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
2969 u32 (*get_expected_throughput)(struct ieee80211_sta *sta);
2965}; 2970};
2966 2971
2967/** 2972/**
@@ -4535,6 +4540,8 @@ struct rate_control_ops {
4535 void (*add_sta_debugfs)(void *priv, void *priv_sta, 4540 void (*add_sta_debugfs)(void *priv, void *priv_sta,
4536 struct dentry *dir); 4541 struct dentry *dir);
4537 void (*remove_sta_debugfs)(void *priv, void *priv_sta); 4542 void (*remove_sta_debugfs)(void *priv, void *priv_sta);
4543
4544 u32 (*get_expected_throughput)(void *priv_sta);
4538}; 4545};
4539 4546
4540static inline int rate_supported(struct ieee80211_sta *sta, 4547static inline int rate_supported(struct ieee80211_sta *sta,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index ac45304590d8..d7513a503be1 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -472,8 +472,10 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
472{ 472{
473 struct ieee80211_sub_if_data *sdata = sta->sdata; 473 struct ieee80211_sub_if_data *sdata = sta->sdata;
474 struct ieee80211_local *local = sdata->local; 474 struct ieee80211_local *local = sdata->local;
475 struct rate_control_ref *ref = local->rate_ctrl;
475 struct timespec uptime; 476 struct timespec uptime;
476 u64 packets = 0; 477 u64 packets = 0;
478 u32 thr = 0;
477 int i, ac; 479 int i, ac;
478 480
479 sinfo->generation = sdata->local->sta_generation; 481 sinfo->generation = sdata->local->sta_generation;
@@ -587,6 +589,17 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
587 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED); 589 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
588 if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) 590 if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
589 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); 591 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
592
593 /* check if the driver has a SW RC implementation */
594 if (ref && ref->ops->get_expected_throughput)
595 thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
596 else
597 thr = drv_get_expected_throughput(local, &sta->sta);
598
599 if (thr != 0) {
600 sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT;
601 sinfo->expected_throughput = thr;
602 }
590} 603}
591 604
592static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = { 605static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index df1d50291344..696ef78b1fb7 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1156,4 +1156,17 @@ static inline void drv_leave_ibss(struct ieee80211_local *local,
1156 trace_drv_return_void(local); 1156 trace_drv_return_void(local);
1157} 1157}
1158 1158
1159static inline u32 drv_get_expected_throughput(struct ieee80211_local *local,
1160 struct ieee80211_sta *sta)
1161{
1162 u32 ret = 0;
1163
1164 trace_drv_get_expected_throughput(sta);
1165 if (local->ops->get_expected_throughput)
1166 ret = local->ops->get_expected_throughput(sta);
1167 trace_drv_return_u32(local, ret);
1168
1169 return ret;
1170}
1171
1159#endif /* __MAC80211_DRIVER_OPS */ 1172#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 26fd94fa0aed..1c1469c36dca 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -657,6 +657,17 @@ minstrel_free(void *priv)
657 kfree(priv); 657 kfree(priv);
658} 658}
659 659
660static u32 minstrel_get_expected_throughput(void *priv_sta)
661{
662 struct minstrel_sta_info *mi = priv_sta;
663 int idx = mi->max_tp_rate[0];
664
665 /* convert pkt per sec in kbps (1200 is the average pkt size used for
666 * computing cur_tp
667 */
668 return MINSTREL_TRUNC(mi->r[idx].cur_tp) * 1200 * 8 / 1024;
669}
670
660const struct rate_control_ops mac80211_minstrel = { 671const struct rate_control_ops mac80211_minstrel = {
661 .name = "minstrel", 672 .name = "minstrel",
662 .tx_status = minstrel_tx_status, 673 .tx_status = minstrel_tx_status,
@@ -670,6 +681,7 @@ const struct rate_control_ops mac80211_minstrel = {
670 .add_sta_debugfs = minstrel_add_sta_debugfs, 681 .add_sta_debugfs = minstrel_add_sta_debugfs,
671 .remove_sta_debugfs = minstrel_remove_sta_debugfs, 682 .remove_sta_debugfs = minstrel_remove_sta_debugfs,
672#endif 683#endif
684 .get_expected_throughput = minstrel_get_expected_throughput,
673}; 685};
674 686
675int __init 687int __init
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 4e916ad51a20..85c1e74b7714 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -1032,6 +1032,22 @@ minstrel_ht_free(void *priv)
1032 mac80211_minstrel.free(priv); 1032 mac80211_minstrel.free(priv);
1033} 1033}
1034 1034
1035static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
1036{
1037 struct minstrel_ht_sta_priv *msp = priv_sta;
1038 struct minstrel_ht_sta *mi = &msp->ht;
1039 int i, j;
1040
1041 if (!msp->is_ht)
1042 return mac80211_minstrel.get_expected_throughput(priv_sta);
1043
1044 i = mi->max_tp_rate / MCS_GROUP_RATES;
1045 j = mi->max_tp_rate % MCS_GROUP_RATES;
1046
1047 /* convert cur_tp from pkt per second in kbps */
1048 return mi->groups[i].rates[j].cur_tp * AVG_PKT_SIZE * 8 / 1024;
1049}
1050
1035static const struct rate_control_ops mac80211_minstrel_ht = { 1051static const struct rate_control_ops mac80211_minstrel_ht = {
1036 .name = "minstrel_ht", 1052 .name = "minstrel_ht",
1037 .tx_status = minstrel_ht_tx_status, 1053 .tx_status = minstrel_ht_tx_status,
@@ -1046,6 +1062,7 @@ static const struct rate_control_ops mac80211_minstrel_ht = {
1046 .add_sta_debugfs = minstrel_ht_add_sta_debugfs, 1062 .add_sta_debugfs = minstrel_ht_add_sta_debugfs,
1047 .remove_sta_debugfs = minstrel_ht_remove_sta_debugfs, 1063 .remove_sta_debugfs = minstrel_ht_remove_sta_debugfs,
1048#endif 1064#endif
1065 .get_expected_throughput = minstrel_ht_get_expected_throughput,
1049}; 1066};
1050 1067
1051 1068
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index a0b0aea76525..942f64b8ce0e 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -184,6 +184,20 @@ TRACE_EVENT(drv_return_bool,
184 "true" : "false") 184 "true" : "false")
185); 185);
186 186
187TRACE_EVENT(drv_return_u32,
188 TP_PROTO(struct ieee80211_local *local, u32 ret),
189 TP_ARGS(local, ret),
190 TP_STRUCT__entry(
191 LOCAL_ENTRY
192 __field(u32, ret)
193 ),
194 TP_fast_assign(
195 LOCAL_ASSIGN;
196 __entry->ret = ret;
197 ),
198 TP_printk(LOCAL_PR_FMT " - %u", LOCAL_PR_ARG, __entry->ret)
199);
200
187TRACE_EVENT(drv_return_u64, 201TRACE_EVENT(drv_return_u64,
188 TP_PROTO(struct ieee80211_local *local, u64 ret), 202 TP_PROTO(struct ieee80211_local *local, u64 ret),
189 TP_ARGS(local, ret), 203 TP_ARGS(local, ret),
@@ -1499,6 +1513,24 @@ DEFINE_EVENT(local_sdata_evt, drv_leave_ibss,
1499 TP_ARGS(local, sdata) 1513 TP_ARGS(local, sdata)
1500); 1514);
1501 1515
1516TRACE_EVENT(drv_get_expected_throughput,
1517 TP_PROTO(struct ieee80211_sta *sta),
1518
1519 TP_ARGS(sta),
1520
1521 TP_STRUCT__entry(
1522 STA_ENTRY
1523 ),
1524
1525 TP_fast_assign(
1526 STA_ASSIGN;
1527 ),
1528
1529 TP_printk(
1530 STA_PR_FMT, STA_PR_ARG
1531 )
1532);
1533
1502/* 1534/*
1503 * Tracing for API calls that drivers call. 1535 * Tracing for API calls that drivers call.
1504 */ 1536 */