diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/driver-ops.h | 8 | ||||
-rw-r--r-- | net/mac80211/driver-trace.h | 46 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 8 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 23 | ||||
-rw-r--r-- | net/mac80211/util.c | 40 |
5 files changed, 125 insertions, 0 deletions
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index edd2dd79c9be..b2d6bba44054 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -657,4 +657,12 @@ static inline void drv_set_rekey_data(struct ieee80211_local *local, trace_drv_return_void(local); } +static inline void drv_rssi_callback(struct ieee80211_local *local, + const enum ieee80211_rssi_event event) +{ + trace_drv_rssi_callback(local, event); + if (local->ops->rssi_callback) + local->ops->rssi_callback(&local->hw, event); + trace_drv_return_void(local); +} #endif /* __MAC80211_DRIVER_OPS */ diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 31a9dfa81f65..4470f6e8b845 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -1052,6 +1052,28 @@ TRACE_EVENT(drv_set_rekey_data, LOCAL_PR_ARG, VIF_PR_ARG) ); +TRACE_EVENT(drv_rssi_callback, + TP_PROTO(struct ieee80211_local *local, + enum ieee80211_rssi_event rssi_event), + + TP_ARGS(local, rssi_event), + + TP_STRUCT__entry( + LOCAL_ENTRY + __field(u32, rssi_event) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + __entry->rssi_event = rssi_event; + ), + + TP_printk( + LOCAL_PR_FMT " rssi_event:%d", + LOCAL_PR_ARG, __entry->rssi_event + ) +); + /* * Tracing for API calls that drivers call. */ @@ -1342,6 +1364,30 @@ TRACE_EVENT(api_gtk_rekey_notify, TP_printk(VIF_PR_FMT, VIF_PR_ARG) ); +TRACE_EVENT(api_enable_rssi_reports, + TP_PROTO(struct ieee80211_sub_if_data *sdata, + int rssi_min_thold, int rssi_max_thold), + + TP_ARGS(sdata, rssi_min_thold, rssi_max_thold), + + TP_STRUCT__entry( + VIF_ENTRY + __field(int, rssi_min_thold) + __field(int, rssi_max_thold) + ), + + TP_fast_assign( + VIF_ASSIGN; + __entry->rssi_min_thold = rssi_min_thold; + __entry->rssi_max_thold = rssi_max_thold; + ), + + TP_printk( + VIF_PR_FMT " rssi_min_thold =%d, rssi_max_thold = %d", + VIF_PR_ARG, __entry->rssi_min_thold, __entry->rssi_max_thold + ) +); + /* * Tracing for internal functions * (which may also be called in response to driver calls) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 4c7a831e7d1e..96600bec44c5 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -432,6 +432,14 @@ struct ieee80211_if_managed { * generated for the current association. */ int last_cqm_event_signal; + + /* + * State variables for keeping track of RSSI of the AP currently + * connected to and informing driver when RSSI has gone + * below/above a certain threshold. + */ + int rssi_min_thold, rssi_max_thold; + int last_ave_beacon_signal; }; struct ieee80211_if_ibss { diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b6d9bd5f4d3c..4b0460ad8c8f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1763,6 +1763,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ifmgd->ave_beacon_signal = rx_status->signal * 16; ifmgd->last_cqm_event_signal = 0; ifmgd->count_beacon_signal = 1; + ifmgd->last_ave_beacon_signal = 0; } else { ifmgd->ave_beacon_signal = (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + @@ -1770,6 +1771,28 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ifmgd->ave_beacon_signal) / 16; ifmgd->count_beacon_signal++; } + + if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold && + ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) { + int sig = ifmgd->ave_beacon_signal; + int last_sig = ifmgd->last_ave_beacon_signal; + + /* + * if signal crosses either of the boundaries, invoke callback + * with appropriate parameters + */ + if (sig > ifmgd->rssi_max_thold && + (last_sig <= ifmgd->rssi_min_thold || last_sig == 0)) { + ifmgd->last_ave_beacon_signal = sig; + drv_rssi_callback(local, RSSI_EVENT_HIGH); + } else if (sig < ifmgd->rssi_min_thold && + (last_sig >= ifmgd->rssi_max_thold || + last_sig == 0)) { + ifmgd->last_ave_beacon_signal = sig; + drv_rssi_callback(local, RSSI_EVENT_LOW); + } + } + if (bss_conf->cqm_rssi_thold && ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 652e5695225a..190132063c99 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1450,3 +1450,43 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset) return pos; } + +static void _ieee80211_enable_rssi_reports(struct ieee80211_sub_if_data *sdata, + int rssi_min_thold, + int rssi_max_thold) +{ + trace_api_enable_rssi_reports(sdata, rssi_min_thold, rssi_max_thold); + + if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) + return; + + /* + * Scale up threshold values before storing it, as the RSSI averaging + * algorithm uses a scaled up value as well. Change this scaling + * factor if the RSSI averaging algorithm changes. + */ + sdata->u.mgd.rssi_min_thold = rssi_min_thold*16; + sdata->u.mgd.rssi_max_thold = rssi_max_thold*16; +} + +void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif, + int rssi_min_thold, + int rssi_max_thold) +{ + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + + WARN_ON(rssi_min_thold == rssi_max_thold || + rssi_min_thold > rssi_max_thold); + + _ieee80211_enable_rssi_reports(sdata, rssi_min_thold, + rssi_max_thold); +} +EXPORT_SYMBOL(ieee80211_enable_rssi_reports); + +void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif) +{ + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + + _ieee80211_enable_rssi_reports(sdata, 0, 0); +} +EXPORT_SYMBOL(ieee80211_disable_rssi_reports); |