Commit cb3a8eec authored by Dan Williams's avatar Dan Williams Committed by John W. Linville

cfg80211: age scan results on resume

Scanned BSS entries are timestamped with jiffies, which doesn't
increment across suspend and hibernate.  On resume, every BSS in the
scan list looks like it was scanned within the last 10 seconds,
irregardless of how long the machine was actually asleep.  Age scan
results on resume with the time spent during sleep so userspace has a
clue how old they really are.
Signed-off-by: default avatarDan Williams <dcbw@redhat.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent abd2fdb4
...@@ -49,6 +49,7 @@ struct cfg80211_registered_device { ...@@ -49,6 +49,7 @@ struct cfg80211_registered_device {
struct rb_root bss_tree; struct rb_root bss_tree;
u32 bss_generation; u32 bss_generation;
struct cfg80211_scan_request *scan_req; /* protected by RTNL */ struct cfg80211_scan_request *scan_req; /* protected by RTNL */
unsigned long suspend_at;
/* must be last because of the way we do wiphy_priv(), /* must be last because of the way we do wiphy_priv(),
* and it should at least be aligned to NETDEV_ALIGN */ * and it should at least be aligned to NETDEV_ALIGN */
...@@ -113,5 +114,7 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy); ...@@ -113,5 +114,7 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby); void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby);
void cfg80211_bss_expire(struct cfg80211_registered_device *dev); void cfg80211_bss_expire(struct cfg80211_registered_device *dev);
void cfg80211_bss_age(struct cfg80211_registered_device *dev,
unsigned long age_secs);
#endif /* __NET_WIRELESS_CORE_H */ #endif /* __NET_WIRELESS_CORE_H */
...@@ -61,6 +61,18 @@ static void bss_release(struct kref *ref) ...@@ -61,6 +61,18 @@ static void bss_release(struct kref *ref)
kfree(bss); kfree(bss);
} }
/* must hold dev->bss_lock! */
void cfg80211_bss_age(struct cfg80211_registered_device *dev,
unsigned long age_secs)
{
struct cfg80211_internal_bss *bss;
unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
list_for_each_entry(bss, &dev->bss_list, list) {
bss->ts -= age_jiffies;
}
}
/* must hold dev->bss_lock! */ /* must hold dev->bss_lock! */
void cfg80211_bss_expire(struct cfg80211_registered_device *dev) void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
{ {
...@@ -584,6 +596,15 @@ static void ieee80211_scan_add_ies(struct iw_request_info *info, ...@@ -584,6 +596,15 @@ static void ieee80211_scan_add_ies(struct iw_request_info *info,
} }
} }
static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
{
unsigned long end = jiffies;
if (end >= start)
return jiffies_to_msecs(end - start);
return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
}
static char * static char *
ieee80211_bss(struct iw_request_info *info, ieee80211_bss(struct iw_request_info *info,
...@@ -763,8 +784,8 @@ ieee80211_bss(struct iw_request_info *info, ...@@ -763,8 +784,8 @@ ieee80211_bss(struct iw_request_info *info,
&iwe, buf); &iwe, buf);
memset(&iwe, 0, sizeof(iwe)); memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVCUSTOM; iwe.cmd = IWEVCUSTOM;
sprintf(buf, " Last beacon: %dms ago", sprintf(buf, " Last beacon: %ums ago",
jiffies_to_msecs(jiffies - bss->ts)); elapsed_jiffies_msecs(bss->ts));
iwe.u.data.length = strlen(buf); iwe.u.data.length = strlen(buf);
current_ev = iwe_stream_add_point(info, current_ev, current_ev = iwe_stream_add_point(info, current_ev,
end_buf, &iwe, buf); end_buf, &iwe, buf);
......
...@@ -60,6 +60,8 @@ static int wiphy_suspend(struct device *dev, pm_message_t state) ...@@ -60,6 +60,8 @@ static int wiphy_suspend(struct device *dev, pm_message_t state)
struct cfg80211_registered_device *rdev = dev_to_rdev(dev); struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
int ret = 0; int ret = 0;
rdev->suspend_at = get_seconds();
if (rdev->ops->suspend) { if (rdev->ops->suspend) {
rtnl_lock(); rtnl_lock();
ret = rdev->ops->suspend(&rdev->wiphy); ret = rdev->ops->suspend(&rdev->wiphy);
...@@ -74,6 +76,11 @@ static int wiphy_resume(struct device *dev) ...@@ -74,6 +76,11 @@ static int wiphy_resume(struct device *dev)
struct cfg80211_registered_device *rdev = dev_to_rdev(dev); struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
int ret = 0; int ret = 0;
/* Age scan results with time spent in suspend */
spin_lock_bh(&rdev->bss_lock);
cfg80211_bss_age(rdev, get_seconds() - rdev->suspend_at);
spin_unlock_bh(&rdev->bss_lock);
if (rdev->ops->resume) { if (rdev->ops->resume) {
rtnl_lock(); rtnl_lock();
ret = rdev->ops->resume(&rdev->wiphy); ret = rdev->ops->resume(&rdev->wiphy);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment