[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