[PATCH] libertas: fix 'keep previous scan' behavior

Dan Williams dcbw at redhat.com
Thu Mar 22 11:17:06 EDT 2007


Do not clear the scan list except under specific conditions, such as
when (a) user-requested, or (b) joining/starting an adhoc network.
Furthermore, only clear entries which match the SSID or BSSID of the
request, not the whole scan list.

Signed-off-by: Dan Williams <dcbw at redhat.com>

Patch applies on top of the "scan handling flexibility" patch.

diff -up libertas-2.6/drivers/net/wireless/libertas-SCAN/assoc.c libertas-2.6/drivers/net/wireless/libertas/assoc.c
--- libertas-2.6/drivers/net/wireless/libertas-SCAN/assoc.c	2007-03-22 08:53:21.000000000 -0400
+++ libertas-2.6/drivers/net/wireless/libertas/assoc.c	2007-03-22 10:19:18.000000000 -0400
@@ -25,7 +25,7 @@ static int assoc_helper_essid(wlan_priva
 	lbs_deb_assoc("New SSID requested: %s\n", assoc_req->ssid.ssid);
 	if (assoc_req->mode == wlan802_11infrastructure) {
 		if (adapter->prescan) {
-			libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 1);
+			libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 0);
 		}
 
 		bss = libertas_find_SSID_in_list(adapter, &assoc_req->ssid,
@@ -44,7 +44,7 @@ static int assoc_helper_essid(wlan_priva
 		/* Scan for the network, do not save previous results.  Stale
 		 *   scan data will cause us to join a non-existant adhoc network
 		 */
-		libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 0);
+		libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 1);
 
 		/* Search for the requested SSID in the scan table */
 		bss = libertas_find_SSID_in_list(adapter, &assoc_req->ssid, NULL,
Common subdirectories: libertas-2.6/drivers/net/wireless/libertas-SCAN/config and libertas-2.6/drivers/net/wireless/libertas/config
diff -up libertas-2.6/drivers/net/wireless/libertas-SCAN/debugfs.c libertas-2.6/drivers/net/wireless/libertas/debugfs.c
--- libertas-2.6/drivers/net/wireless/libertas-SCAN/debugfs.c	2007-03-22 08:53:22.000000000 -0400
+++ libertas-2.6/drivers/net/wireless/libertas/debugfs.c	2007-03-22 10:34:01.000000000 -0400
@@ -193,7 +193,7 @@ static ssize_t libertas_extscan(struct f
 	memcpy(&extscan_ssid.ssid, buf, strlen(buf)-1);
 	extscan_ssid.ssidlength = strlen(buf)-1;
 
-	libertas_send_specific_SSID_scan(priv, &extscan_ssid, 1);
+	libertas_send_specific_SSID_scan(priv, &extscan_ssid, 0);
 
 	memset(&wrqu, 0, sizeof(union iwreq_data));
 	wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
@@ -245,16 +245,13 @@ static void libertas_parse_bssid(char *b
 {
 	char *hold;
 	unsigned int mac[ETH_ALEN];
-	int i;
 	
 	hold = strstr(buf, "bssid=");
 	if (!hold)
 		return;
 	hold += 6;
-	sscanf(hold, "%2x:%2x:%2x:%2x:%2x:%2x", mac, mac+1, mac+2, mac+3, 
-			mac+4, mac+5);
-	for(i=0;i<ETH_ALEN;i++)
-		scan_cfg->specificBSSID[i] = mac[i];
+	sscanf(hold, MAC_FMT, mac, mac+1, mac+2, mac+3, mac+4, mac+5);
+	memcpy(scan_cfg->bssid, mac, ETH_ALEN);
 }
 
 static void libertas_parse_ssid(char *buf, size_t count,
@@ -272,28 +269,26 @@ static void libertas_parse_ssid(char *bu
 		end = buf + count - 1;
 
 	size = min(IW_ESSID_MAX_SIZE, end - hold);
-	strncpy(scan_cfg->specificSSID, hold, size);
+	strncpy(scan_cfg->ssid, hold, size);
 
 	return;
 }	
 
-static void libertas_parse_keep(char *buf, size_t count,
-                        struct wlan_ioctl_user_scan_cfg *scan_cfg)
+static int libertas_parse_clear(char *buf, size_t count, const char *tag)
 {
 	char *hold;
 	int val;
 
-	hold = strstr(buf, "keep=");
+	hold = strstr(buf, tag);
 	if (!hold)
-		return;
-	hold += 5;
+		return 0;
+	hold += strlen(tag);
 	sscanf(hold, "%d", &val);
 
 	if (val != 0)
 		val = 1;
 
-	scan_cfg->keeppreviousscan = val;
-	return;
+	return val;
 }
 
 static int libertas_parse_dur(char *buf, size_t count,
@@ -376,8 +371,9 @@ static ssize_t libertas_setuserscan(stru
 	dur = libertas_parse_dur(buf, count, scan_cfg);
 	libertas_parse_chan(buf, count, scan_cfg, dur);
 	libertas_parse_bssid(buf, count, scan_cfg);
+	scan_cfg->clear_bssid = libertas_parse_clear(buf, count, "clear_bssid=");
 	libertas_parse_ssid(buf, count, scan_cfg);
-	libertas_parse_keep(buf, count, scan_cfg);
+	scan_cfg->clear_ssid = libertas_parse_clear(buf, count, "clear_ssid=");
 	libertas_parse_probes(buf, count, scan_cfg);
 	libertas_parse_type(buf, count, scan_cfg);
 
diff -up libertas-2.6/drivers/net/wireless/libertas-SCAN/join.c libertas-2.6/drivers/net/wireless/libertas/join.c
--- libertas-2.6/drivers/net/wireless/libertas-SCAN/join.c	2007-03-22 08:53:23.000000000 -0400
+++ libertas-2.6/drivers/net/wireless/libertas/join.c	2007-03-22 10:25:02.000000000 -0400
@@ -304,7 +304,7 @@ int libertas_idle_off(wlan_private * pri
 	found = libertas_find_SSID_in_list(adapter, prev_ssid,
 			prev_bssid, adapter->inframode);
 	if (found == NULL) {
-		libertas_send_specific_BSSID_scan(priv, prev_bssid, 1);
+		libertas_send_specific_BSSID_scan(priv, prev_bssid, 0);
 		found = libertas_find_SSID_in_list(adapter, prev_ssid,
 				prev_bssid, adapter->inframode);
 	}
@@ -316,7 +316,7 @@ int libertas_idle_off(wlan_private * pri
 	}
 
 	if (found == NULL) {
-		libertas_send_specific_SSID_scan(priv, prev_ssid, 1);
+		libertas_send_specific_SSID_scan(priv, prev_ssid, 0);
 		found = libertas_find_SSID_in_list(adapter, prev_ssid,
 				NULL, adapter->inframode);
 	}
diff -up libertas-2.6/drivers/net/wireless/libertas-SCAN/scan.c libertas-2.6/drivers/net/wireless/libertas/scan.c
--- libertas-2.6/drivers/net/wireless/libertas-SCAN/scan.c	2007-03-22 08:53:20.000000000 -0400
+++ libertas-2.6/drivers/net/wireless/libertas/scan.c	2007-03-22 10:59:36.000000000 -0400
@@ -62,6 +62,9 @@
 //! Scan time specified in the channel TLV for each channel for active scans
 #define MRVDRV_ACTIVE_SCAN_CHAN_TIME   100
 
+const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
 static inline void clear_bss_descriptor (struct bss_descriptor * bss)
 {
 	/* Don't blow away ->list, just BSS data */
@@ -419,13 +422,11 @@ wlan_scan_setup_scan_config(wlan_private
 			    u8 * pscancurrentonly)
 {
 	wlan_adapter *adapter = priv->adapter;
-	const u8 zeromac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
 	struct mrvlietypes_numprobes *pnumprobestlv;
 	struct mrvlietypes_ssidparamset *pssidtlv;
 	struct wlan_scan_cmd_config * pscancfgout = NULL;
 	u8 *ptlvpos;
 	u16 numprobes;
-	u16 ssidlen;
 	int chanidx;
 	int scantype;
 	int scandur;
@@ -482,21 +483,18 @@ wlan_scan_setup_scan_config(wlan_private
 		 * Set the BSSID filter to the incoming configuration,
 		 *   if non-zero.  If not set, it will remain disabled (all zeros).
 		 */
-		memcpy(pscancfgout->specificBSSID,
-		       puserscanin->specificBSSID,
-		       sizeof(pscancfgout->specificBSSID));
-
-		ssidlen = strlen(puserscanin->specificSSID);
+		memcpy(pscancfgout->bssid, puserscanin->bssid,
+		       sizeof(pscancfgout->bssid));
 
-		if (ssidlen) {
+		if (puserscanin->ssid_len) {
 			pssidtlv =
 			    (struct mrvlietypes_ssidparamset *) pscancfgout->
 			    tlvbuffer;
 			pssidtlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
-			pssidtlv->header.len = cpu_to_le16(ssidlen);
-			memcpy(pssidtlv->ssid, puserscanin->specificSSID,
-			       ssidlen);
-			ptlvpos += sizeof(pssidtlv->header) + ssidlen;
+			pssidtlv->header.len = cpu_to_le16(puserscanin->ssid_len);
+			memcpy(pssidtlv->ssid, puserscanin->ssid,
+			       puserscanin->ssid_len);
+			ptlvpos += sizeof(pssidtlv->header) + puserscanin->ssid_len;
 		}
 
 		/*
@@ -505,8 +503,8 @@ wlan_scan_setup_scan_config(wlan_private
 		 *    scan results.  That is not an issue with an SSID or BSSID
 		 *    filter applied to the scan results in the firmware.
 		 */
-		if (ssidlen || (memcmp(pscancfgout->specificBSSID,
-				       &zeromac, sizeof(zeromac)) != 0)) {
+		if (   puserscanin->ssid_len
+		    || (compare_ether_addr(pscancfgout->bssid, &zeromac[0]) != 0)) {
 			*pmaxchanperscan = MRVDRV_MAX_CHANNELS_PER_SCAN;
 			*pfilteredscan = 1;
 		}
@@ -754,6 +752,53 @@ done:
 	return ret;
 }
 
+static void
+clear_selected_scan_list_entries(wlan_adapter * adapter, 
+                                 const struct wlan_ioctl_user_scan_cfg * scan_cfg)
+{
+	struct bss_descriptor * bss;
+	struct bss_descriptor * safe;
+	u32 clear_ssid_flag = 0, clear_bssid_flag = 0;
+
+	if (!scan_cfg)
+		return;
+
+	if (scan_cfg->clear_ssid && scan_cfg->ssid_len)
+		clear_ssid_flag = 1;
+
+	if (scan_cfg->clear_bssid
+	    && (compare_ether_addr(scan_cfg->bssid, &zeromac[0]) != 0)
+	    && (compare_ether_addr(scan_cfg->bssid, &bcastmac[0]) != 0)) {
+		clear_bssid_flag = 1;
+	}
+
+	if (!clear_ssid_flag && !clear_bssid_flag)
+		return;
+
+	mutex_lock(&adapter->lock);
+	list_for_each_entry_safe (bss, safe, &adapter->network_list, list) {
+		u32 clear = 0;
+
+		/* Check for an SSID match */
+		if (   clear_ssid_flag
+		    && (bss->ssid.ssidlength == scan_cfg->ssid_len)
+		    && !memcmp(bss->ssid.ssid, scan_cfg->ssid, bss->ssid.ssidlength))
+			clear = 1;
+
+		/* Check for a BSSID match */
+		if (   clear_bssid_flag
+		    && !compare_ether_addr(bss->bssid, scan_cfg->bssid))
+			clear = 1;
+
+		if (clear) {
+			list_move_tail (&bss->list, &adapter->network_free_list);
+			clear_bss_descriptor(bss);
+		}
+	}
+	mutex_unlock(&adapter->lock);
+}
+                        
+
 /**
  *  @brief Internal function used to start a scan based on an input config
  *
@@ -771,11 +816,10 @@ int wlan_scan_networks(wlan_private * pr
 			      const struct wlan_ioctl_user_scan_cfg * puserscanin,
 			      int full_scan)
 {
-	wlan_adapter *adapter = priv->adapter;
+	wlan_adapter * adapter = priv->adapter;
 	struct mrvlietypes_chanlistparamset *pchantlvout;
 	struct chanscanparamset * scan_chan_list = NULL;
 	struct wlan_scan_cmd_config * scan_cfg = NULL;
-	u8 keeppreviousscan;
 	u8 filteredscan;
 	u8 scancurrentchanonly;
 	int maxchanperscan;
@@ -802,28 +846,7 @@ int wlan_scan_networks(wlan_private * pr
 		goto out;
  	}
 
-	keeppreviousscan = 0;
-
-	if (puserscanin) {
-		keeppreviousscan = puserscanin->keeppreviousscan;
-	}
-
-	if (adapter->last_scanned_channel)
-		keeppreviousscan = 1;
-
-	if (!keeppreviousscan) {
-		struct bss_descriptor * iter_bss;
-		struct bss_descriptor * safe;
-
-		mutex_lock(&adapter->lock);
-		list_for_each_entry_safe (iter_bss, safe,
-				&adapter->network_list, list) {
-			list_move_tail (&iter_bss->list,
-			                &adapter->network_free_list);
-			clear_bss_descriptor(iter_bss);
-		}
-		mutex_unlock(&adapter->lock);
-	}
+	clear_selected_scan_list_entries(adapter, puserscanin);
 
 	/* Keep the data path active if we are only scanning our current channel */
 	if (!scancurrentchanonly) {
@@ -1444,30 +1467,30 @@ int libertas_set_scan(struct net_device 
  */
 int libertas_send_specific_SSID_scan(wlan_private * priv,
 			 struct WLAN_802_11_SSID *prequestedssid,
-			 u8 keeppreviousscan)
+			 u8 clear_ssid)
 {
 	wlan_adapter *adapter = priv->adapter;
 	struct wlan_ioctl_user_scan_cfg scancfg;
+	int ret = 0;
 
 	lbs_deb_enter(LBS_DEB_ASSOC);
 
-	if (prequestedssid == NULL) {
-		return -1;
-	}
+	if (prequestedssid == NULL)
+		goto out;
 
 	memset(&scancfg, 0x00, sizeof(scancfg));
-
-	memcpy(scancfg.specificSSID, prequestedssid->ssid,
-	       prequestedssid->ssidlength);
-	scancfg.keeppreviousscan = keeppreviousscan;
+	memcpy(scancfg.ssid, prequestedssid->ssid, prequestedssid->ssidlength);
+	scancfg.ssid_len = prequestedssid->ssidlength;
+	scancfg.clear_ssid = clear_ssid;
 
 	wlan_scan_networks(priv, &scancfg, 1);
 	if (adapter->surpriseremoved)
 		return -1;
 	wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending);
 
+out:
 	lbs_deb_leave(LBS_DEB_ASSOC);
-	return 0;
+	return ret;
 }
 
 /**
@@ -1479,19 +1502,18 @@ int libertas_send_specific_SSID_scan(wla
  *
  *  @return          0-success, otherwise fail
  */
-int libertas_send_specific_BSSID_scan(wlan_private * priv, u8 * bssid, u8 keeppreviousscan)
+int libertas_send_specific_BSSID_scan(wlan_private * priv, u8 * bssid, u8 clear_bssid)
 {
 	struct wlan_ioctl_user_scan_cfg scancfg;
 
 	lbs_deb_enter(LBS_DEB_ASSOC);
 
-	if (bssid == NULL) {
-		return -1;
-	}
+	if (bssid == NULL)
+		goto out;
 
 	memset(&scancfg, 0x00, sizeof(scancfg));
-	memcpy(scancfg.specificBSSID, bssid, sizeof(scancfg.specificBSSID));
-	scancfg.keeppreviousscan = keeppreviousscan;
+	memcpy(scancfg.bssid, bssid, ETH_ALEN);
+	scancfg.clear_bssid = clear_bssid;
 
 	wlan_scan_networks(priv, &scancfg, 1);
 	if (priv->adapter->surpriseremoved)
@@ -1499,6 +1521,7 @@ int libertas_send_specific_BSSID_scan(wl
 	wait_event_interruptible(priv->adapter->cmd_pending,
 		!priv->adapter->nr_cmd_pending);
 
+out:
 	lbs_deb_leave(LBS_DEB_ASSOC);
 	return 0;
 }
@@ -1737,7 +1760,7 @@ int libertas_cmd_80211_scan(wlan_private
 
 	/* Set fixed field variables in scan command */
 	pscan->bsstype = pscancfg->bsstype;
-	memcpy(pscan->BSSID, pscancfg->specificBSSID, sizeof(pscan->BSSID));
+	memcpy(pscan->BSSID, pscancfg->bssid, sizeof(pscan->BSSID));
 	memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen);
 
 	cmd->command = cpu_to_le16(cmd_802_11_scan);
diff -up libertas-2.6/drivers/net/wireless/libertas-SCAN/scan.h libertas-2.6/drivers/net/wireless/libertas/scan.h
--- libertas-2.6/drivers/net/wireless/libertas-SCAN/scan.h	2007-03-22 08:53:22.000000000 -0400
+++ libertas-2.6/drivers/net/wireless/libertas/scan.h	2007-03-22 10:31:03.000000000 -0400
@@ -54,7 +54,7 @@ struct wlan_scan_cmd_config {
     /**
      *  @brief Specific BSSID used to filter scan results in the firmware
      */
-	u8 specificBSSID[ETH_ALEN];
+	u8 bssid[ETH_ALEN];
 
     /**
      *  @brief length of TLVs sent in command starting at tlvBuffer
@@ -94,15 +94,6 @@ struct wlan_ioctl_user_scan_chan {
  *  @sa libertas_set_user_scan_ioctl
  */
 struct wlan_ioctl_user_scan_cfg {
-
-    /**
-     *  @brief Flag set to keep the previous scan table intact
-     *
-     *  If set, the scan results will accumulate, replacing any previous
-     *   matched entries for a BSS with the new scan data
-     */
-	u8 keeppreviousscan;	//!< Do not erase the existing scan results
-
     /**
      *  @brief BSS type to be sent in the firmware command
      *
@@ -120,15 +111,22 @@ struct wlan_ioctl_user_scan_cfg {
      */
 	u8 numprobes;
 
-    /**
-     *  @brief BSSID filter sent in the firmware command to limit the results
-     */
-	u8 specificBSSID[ETH_ALEN];
+	/**
+	 *  @brief BSSID filter sent in the firmware command to limit the results
+	 */
+	u8 bssid[ETH_ALEN];
 
-    /**
-     *  @brief SSID filter sent in the firmware command to limit the results
-     */
-	char specificSSID[IW_ESSID_MAX_SIZE + 1];
+	/* Clear existing scan results matching this BSSID */
+	u8 clear_bssid;
+
+	/**
+	 *  @brief SSID filter sent in the firmware command to limit the results
+	 */
+	char ssid[IW_ESSID_MAX_SIZE];
+	u8 ssid_len;
+
+	/* Clear existing scan results matching this SSID */
+	u8 clear_ssid;
 
     /**
      *  @brief Variable number (fixed maximum) of channels to scan up
@@ -198,9 +196,9 @@ int libertas_find_best_network_SSID(wlan
 
 extern int libertas_send_specific_SSID_scan(wlan_private * priv,
 				struct WLAN_802_11_SSID *prequestedssid,
-				u8 keeppreviousscan);
+				u8 clear_ssid);
 extern int libertas_send_specific_BSSID_scan(wlan_private * priv,
-				 u8 * bssid, u8 keeppreviousscan);
+				 u8 * bssid, u8 clear_bssid);
 
 extern int libertas_cmd_80211_scan(wlan_private * priv,
 				struct cmd_ds_command *cmd,
diff -up libertas-2.6/drivers/net/wireless/libertas-SCAN/wext.c libertas-2.6/drivers/net/wireless/libertas/wext.c
--- libertas-2.6/drivers/net/wireless/libertas-SCAN/wext.c	2007-03-22 08:53:21.000000000 -0400
+++ libertas-2.6/drivers/net/wireless/libertas/wext.c	2007-03-22 10:20:59.000000000 -0400
@@ -235,7 +235,7 @@ static int changeadhocchannel(wlan_priva
 	/* Scan for the network, do not save previous results.  Stale
 	 *   scan data will cause us to join a non-existant adhoc network
 	 */
-	libertas_send_specific_SSID_scan(priv, &curadhocssid, 0);
+	libertas_send_specific_SSID_scan(priv, &curadhocssid, 1);
 
 	/* find out the BSSID that matches the current SSID */
 	join_bss = libertas_find_SSID_in_list(adapter, &curadhocssid, NULL,





More information about the libertas-dev mailing list