From: Dan Williams Date: Fri, 25 May 2007 20:25:21 +0000 (-0400) Subject: [PATCH] libertas: fix 'keep previous scan' behavior X-Git-Tag: v2.6.22-rc5~44^2~2^2~31 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eb8f7330e7edf655176c51a62cd2e34de91a1eba;p=linux-2.6 [PATCH] libertas: fix 'keep previous scan' behavior 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 Signed-off-by: John W. Linville --- diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 4605bd3a26..4bc128fa58 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -25,7 +25,7 @@ static int assoc_helper_essid(wlan_private *priv, lbs_deb_assoc("New SSID requested: %s\n", assoc_req->ssid.ssid); if (assoc_req->mode == IW_MODE_INFRA) { 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_private *priv, /* 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, diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index c26227adf8..1545935f7a 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -193,7 +193,7 @@ static ssize_t libertas_extscan(struct file *file, const char __user *userbuf, 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 *buf, size_t count, { 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;ispecificBSSID[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 *buf, size_t count, end = buf + count - 1; size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (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(struct file *file, 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 --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index b2919a6876..437a1e9867 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -59,6 +59,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 */ @@ -409,13 +412,11 @@ wlan_scan_setup_scan_config(wlan_private * priv, 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; @@ -472,21 +473,18 @@ wlan_scan_setup_scan_config(wlan_private * priv, * 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; } /* @@ -495,8 +493,8 @@ wlan_scan_setup_scan_config(wlan_private * priv, * 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; } @@ -743,6 +741,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 * @@ -760,11 +805,10 @@ int wlan_scan_networks(wlan_private * priv, 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; @@ -791,28 +835,7 @@ int wlan_scan_networks(wlan_private * priv, 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) { @@ -1434,30 +1457,30 @@ int libertas_set_scan(struct net_device *dev, struct iw_request_info *info, */ 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; } /** @@ -1469,19 +1492,18 @@ int libertas_send_specific_SSID_scan(wlan_private * priv, * * @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) @@ -1489,6 +1511,7 @@ int libertas_send_specific_BSSID_scan(wlan_private * priv, u8 * bssid, u8 keeppr wait_event_interruptible(priv->adapter->cmd_pending, !priv->adapter->nr_cmd_pending); +out: lbs_deb_leave(LBS_DEB_ASSOC); return 0; } @@ -1727,7 +1750,7 @@ int libertas_cmd_80211_scan(wlan_private * priv, /* 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 --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h index 7427078506..4ad130ff6e 100644 --- a/drivers/net/wireless/libertas/scan.h +++ b/drivers/net/wireless/libertas/scan.h @@ -51,7 +51,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 @@ -91,15 +91,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 * @@ -117,15 +108,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 @@ -194,9 +192,9 @@ int libertas_find_best_network_SSID(wlan_private * priv, 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 --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 4759aa2bba..518371a76c 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -234,7 +234,7 @@ static int changeadhocchannel(wlan_private * priv, int channel) /* 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,