cfg80211: allow RSSI compensation
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sun, 18 May 2014 07:15:24 +0000 (10:15 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 22 May 2014 07:58:49 +0000 (09:58 +0200)
Channels in 2.4GHz band overlap, this means that if we
send a probe request on channel 1 and then move to channel
2, we will hear the probe response on channel 2. In this
case, the RSSI will be lower than if we had heard it on
the channel on which it was sent (1 in this case).

The firmware / low level driver can parse the channel in
the DS IE or HT IE and compensate the RSSI so that it will
still have a valid value even if we heard the frame on an
adjacent channel. This can be done up to a certain offset.

Add this offset as a configuration for the low level driver.
A low level driver that can compensate the low RSSI in this
case should assign the maximal offset for which the RSSI
value is still valid.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
net/wireless/scan.c

index a75fabd185028d5a9c8c507167d268f5afaba385..920ec8c1ce541305bb2d1da9d9c8f178b14bd23d 100644 (file)
@@ -2961,6 +2961,12 @@ struct wiphy_vendor_command {
  *     and probe responses.  This value should be set if the driver
  *     wishes to limit the number of csa counters. Default (0) means
  *     infinite.
+ * @max_adj_channel_rssi_comp: max offset of between the channel on which the
+ *     frame was sent and the channel on which the frame was heard for which
+ *     the reported rssi is still valid. If a driver is able to compensate the
+ *     low rssi when a frame is heard on different channel, then it should set
+ *     this variable to the maximal offset for which it can compensate.
+ *     This value should be set in MHz.
  */
 struct wiphy {
        /* assign these fields before you register the wiphy */
@@ -3079,6 +3085,7 @@ struct wiphy {
        u16 max_ap_assoc_sta;
 
        u8 max_num_csa_counters;
+       u8 max_adj_channel_rssi_comp;
 
        char priv[0] __aligned(NETDEV_ALIGN);
 };
index 0f5da18cc6193b648a4a05f19aa6fe7627f5adbf..77c56eef0574874cb135545938f6cf247cacfa6e 100644 (file)
@@ -883,6 +883,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
        struct cfg80211_bss_ies *ies;
        struct ieee80211_channel *channel;
        struct cfg80211_internal_bss tmp = {}, *res;
+       bool signal_valid;
 
        if (WARN_ON(!wiphy))
                return NULL;
@@ -919,8 +920,9 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
        rcu_assign_pointer(tmp.pub.beacon_ies, ies);
        rcu_assign_pointer(tmp.pub.ies, ies);
 
-       res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp,
-                                 rx_channel == channel);
+       signal_valid = abs(rx_channel->center_freq - channel->center_freq) <=
+               wiphy->max_adj_channel_rssi_comp;
+       res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid);
        if (!res)
                return NULL;
 
@@ -944,6 +946,7 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
        struct cfg80211_internal_bss tmp = {}, *res;
        struct cfg80211_bss_ies *ies;
        struct ieee80211_channel *channel;
+       bool signal_valid;
        size_t ielen = len - offsetof(struct ieee80211_mgmt,
                                      u.probe_resp.variable);
 
@@ -991,8 +994,9 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
        tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
        tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
 
-       res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp,
-                                 rx_channel == channel);
+       signal_valid = abs(rx_channel->center_freq - channel->center_freq) <=
+               wiphy->max_adj_channel_rssi_comp;
+       res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid);
        if (!res)
                return NULL;