]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/libertas/scan.c
[PATCH] libertas: fix 'keep previous scan' behavior
[karo-tx-linux.git] / drivers / net / wireless / libertas / scan.c
index b2919a6876e6d8df24ea0c8c73e7e19f72cf13d4..437a1e98671fb1b5272055d2850f27e70a8c7109 100644 (file)
@@ -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);