Index: linux-wl/net/wireless/core.h
===================================================================
--- linux-wl.orig/net/wireless/core.h	2009-09-18 14:49:42.000000000 +0200
+++ linux-wl/net/wireless/core.h	2009-09-18 17:31:05.000000000 +0200
@@ -270,7 +270,9 @@ void ieee80211_set_bitrate_flags(struct 
 void wiphy_update_regulatory(struct wiphy *wiphy,
 			     enum nl80211_reg_initiator setby);
 
-void cfg80211_bss_expire(struct cfg80211_registered_device *dev);
+#define IEEE80211_SCAN_RESULT_EXPIRE	(15 * HZ)
+
+void cfg80211_bss_expire(struct cfg80211_registered_device *dev, int expire);
 void cfg80211_bss_age(struct cfg80211_registered_device *dev,
                       unsigned long age_secs);
 
Index: linux-wl/net/wireless/nl80211.c
===================================================================
--- linux-wl.orig/net/wireless/nl80211.c	2009-09-18 14:49:42.000000000 +0200
+++ linux-wl/net/wireless/nl80211.c	2009-09-18 17:36:04.000000000 +0200
@@ -138,6 +138,7 @@ static struct nla_policy nl80211_policy[
 	[NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
 	[NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
 	[NL80211_ATTR_PID] = { .type = NLA_U32 },
+	[NL80211_ATTR_SCAN_EXPIRE] = { .type = NLA_U32 },
 };
 
 /* policy for the attributes */
@@ -2945,6 +2946,13 @@ static int nl80211_trigger_scan(struct s
 		goto out;
 	}
 
+	if (info->attrs[NL80211_ATTR_SCAN_EXPIRE]) {
+		u32 expire = nla_get_u32(info->attrs[NL80211_ATTR_SCAN_EXPIRE]);
+		spin_lock_bh(&rdev->bss_lock);
+		cfg80211_bss_expire(rdev, expire);
+		spin_unlock_bh(&rdev->bss_lock);
+	}
+
 	if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
 		n_channels = validate_scan_freqs(
 				info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
@@ -3158,11 +3166,13 @@ static int nl80211_dump_scan(struct sk_b
 	int ifidx = cb->args[0];
 	int start = cb->args[1], idx = 0;
 	int err;
+	u32 expire = IEEE80211_SCAN_RESULT_EXPIRE;
+
+	err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
+			  nl80211_fam.attrbuf, nl80211_fam.maxattr,
+			  nl80211_policy);
 
 	if (!ifidx) {
-		err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
-				  nl80211_fam.attrbuf, nl80211_fam.maxattr,
-				  nl80211_policy);
 		if (err)
 			return err;
 
@@ -3187,9 +3197,20 @@ static int nl80211_dump_scan(struct sk_b
 
 	wdev = dev->ieee80211_ptr;
 
+	/*
+	 * If expire is set (the default), expire the BSS list before
+	 * returning values. However, user-space can set a different
+	 * expire time via NL80211_ATTR_SCAN_EXPIRE. It can also set
+	 * no expire-time at all, then we skip the expiration.
+	 */
+	if (!err && nl80211_fam.attrbuf[NL80211_ATTR_SCAN_EXPIRE])
+		expire =
+		nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_SCAN_EXPIRE]);
+
 	wdev_lock(wdev);
 	spin_lock_bh(&rdev->bss_lock);
-	cfg80211_bss_expire(rdev);
+	if (expire)
+		cfg80211_bss_expire(rdev, expire);
 
 	list_for_each_entry(scan, &rdev->bss_list, list) {
 		if (++idx <= start)
Index: linux-wl/net/wireless/scan.c
===================================================================
--- linux-wl.orig/net/wireless/scan.c	2009-09-18 14:49:42.000000000 +0200
+++ linux-wl/net/wireless/scan.c	2009-09-18 17:32:08.000000000 +0200
@@ -16,8 +16,6 @@
 #include "nl80211.h"
 #include "wext-compat.h"
 
-#define IEEE80211_SCAN_RESULT_EXPIRE	(15 * HZ)
-
 void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
 {
 	struct cfg80211_scan_request *request;
@@ -121,7 +119,7 @@ void cfg80211_bss_age(struct cfg80211_re
 }
 
 /* must hold dev->bss_lock! */
-void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
+void cfg80211_bss_expire(struct cfg80211_registered_device *dev, int expire)
 {
 	struct cfg80211_internal_bss *bss, *tmp;
 	bool expired = false;
@@ -129,7 +127,11 @@ void cfg80211_bss_expire(struct cfg80211
 	list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
 		if (atomic_read(&bss->hold))
 			continue;
-		if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
+		/*
+		 * If expire==0, then expire all BSS from the list,
+		 * else only expire those that are older than expire.
+		 */
+		if (expire && !time_after(jiffies, bss->ts + expire))
 			continue;
 		list_del(&bss->list);
 		rb_erase(&bss->rbn, &dev->bss_tree);
@@ -970,9 +972,11 @@ static int ieee80211_scan_results(struct
 	char *current_ev = buf;
 	char *end_buf = buf + len;
 	struct cfg80211_internal_bss *bss;
+	u32 expire = IEEE80211_SCAN_RESULT_EXPIRE;
 
 	spin_lock_bh(&dev->bss_lock);
-	cfg80211_bss_expire(dev);
+	if (expire)
+		cfg80211_bss_expire(dev, expire);
 
 	list_for_each_entry(bss, &dev->bss_list, list) {
 		if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
Index: linux-wl/include/linux/nl80211.h
===================================================================
--- linux-wl.orig/include/linux/nl80211.h	2009-09-18 15:10:53.000000000 +0200
+++ linux-wl/include/linux/nl80211.h	2009-09-18 15:11:44.000000000 +0200
@@ -481,6 +481,7 @@ enum nl80211_commands {
  * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive
  *	scanning and include a zero-length SSID (wildcard) for wildcard scan
  * @NL80211_ATTR_BSS: scan result BSS
+ * @NL80211_ATTR_SCAN: expire time for cached bss list
  *
  * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain
  * 	currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_*
@@ -714,6 +715,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_PID,
 
+	NL80211_ATTR_SCAN_EXPIRE,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
