Skip to content

Commit

Permalink
mac80211: add command to get current rssi
Browse files Browse the repository at this point in the history
Get current rssi (in dBm) from the driver/FW.

Instead of reporting the signal received in the last
rx packet, which might be inaccurate if rx traffic is
low and beacon filtering is enabled, get the signal
from the driver/FW.

Signed-off-by: Victor Goldenshtein <victorg@ti.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Victor Goldenshtein authored and Johannes Berg committed Jun 21, 2012
1 parent 0f6b3f5 commit 66572cf
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 8 deletions.
5 changes: 5 additions & 0 deletions include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -2249,6 +2249,9 @@ enum ieee80211_rate_control_changed {
* @get_et_strings: Ethtool API to get a set of strings to describe stats
* and perhaps other supported types of ethtool data-sets.
*
* @get_rssi: Get current signal strength in dBm, the function is optional
* and can sleep.
*
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
Expand Down Expand Up @@ -2388,6 +2391,8 @@ struct ieee80211_ops {
void (*get_et_strings)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u32 sset, u8 *data);
int (*get_rssi)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, s8 *rssi_dbm);
};

/**
Expand Down
21 changes: 13 additions & 8 deletions net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ void sta_set_rate_info_tx(struct sta_info *sta,
static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
struct ieee80211_local *local = sdata->local;
struct timespec uptime;

sinfo->generation = sdata->local->sta_generation;
Expand Down Expand Up @@ -388,7 +389,9 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
(sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG;
sinfo->signal = (s8)sta->last_signal;
if (!local->ops->get_rssi ||
drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal))
sinfo->signal = (s8)sta->last_signal;
sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
}

Expand Down Expand Up @@ -517,7 +520,7 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
* network device.
*/

rcu_read_lock();
mutex_lock(&local->sta_mtx);

if (sdata->vif.type == NL80211_IFTYPE_STATION) {
sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid);
Expand Down Expand Up @@ -546,7 +549,7 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
data[i] = (u8)sinfo.signal_avg;
i++;
} else {
list_for_each_entry_rcu(sta, &local->sta_list, list) {
list_for_each_entry(sta, &local->sta_list, list) {
/* Make sure this station belongs to the proper dev */
if (sta->sdata->dev != dev)
continue;
Expand Down Expand Up @@ -603,7 +606,7 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
else
data[i++] = -1LL;

rcu_read_unlock();
mutex_unlock(&local->sta_mtx);

if (WARN_ON(i != STA_STATS_LEN))
return;
Expand All @@ -629,10 +632,11 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
int idx, u8 *mac, struct station_info *sinfo)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
int ret = -ENOENT;

rcu_read_lock();
mutex_lock(&local->sta_mtx);

sta = sta_info_get_by_idx(sdata, idx);
if (sta) {
Expand All @@ -641,7 +645,7 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
sta_set_sinfo(sta, sinfo);
}

rcu_read_unlock();
mutex_unlock(&local->sta_mtx);

return ret;
}
Expand All @@ -658,18 +662,19 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
u8 *mac, struct station_info *sinfo)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
int ret = -ENOENT;

rcu_read_lock();
mutex_lock(&local->sta_mtx);

sta = sta_info_get_bss(sdata, mac);
if (sta) {
ret = 0;
sta_set_sinfo(sta, sinfo);
}

rcu_read_unlock();
mutex_unlock(&local->sta_mtx);

return ret;
}
Expand Down
15 changes: 15 additions & 0 deletions net/mac80211/driver-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -845,4 +845,19 @@ drv_allow_buffered_frames(struct ieee80211_local *local,
more_data);
trace_drv_return_void(local);
}

static inline int drv_get_rssi(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta *sta,
s8 *rssi_dbm)
{
int ret;

might_sleep();

ret = local->ops->get_rssi(&local->hw, &sdata->vif, sta, rssi_dbm);
trace_drv_get_rssi(local, sta, *rssi_dbm, ret);

return ret;
}
#endif /* __MAC80211_DRIVER_OPS */
26 changes: 26 additions & 0 deletions net/mac80211/driver-trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,32 @@ DEFINE_EVENT(release_evt, drv_allow_buffered_frames,
TP_ARGS(local, sta, tids, num_frames, reason, more_data)
);

TRACE_EVENT(drv_get_rssi,
TP_PROTO(struct ieee80211_local *local, struct ieee80211_sta *sta,
s8 rssi, int ret),

TP_ARGS(local, sta, rssi, ret),

TP_STRUCT__entry(
LOCAL_ENTRY
STA_ENTRY
__field(s8, rssi)
__field(int, ret)
),

TP_fast_assign(
LOCAL_ASSIGN;
STA_ASSIGN;
__entry->rssi = rssi;
__entry->ret = ret;
),

TP_printk(
LOCAL_PR_FMT STA_PR_FMT " rssi:%d ret:%d",
LOCAL_PR_ARG, STA_PR_ARG, __entry->rssi, __entry->ret
)
);

/*
* Tracing for API calls that drivers call.
*/
Expand Down

0 comments on commit 66572cf

Please sign in to comment.