diff options
author | Dan Williams <dcbw@redhat.com> | 2007-05-25 16:25:21 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2007-06-11 14:28:41 -0400 |
commit | eb8f7330e7edf655176c51a62cd2e34de91a1eba (patch) | |
tree | 383f19fd3741a2f240c976ee7dc89368581ac1f0 /drivers/net/wireless/libertas/scan.c | |
parent | fcdb53dbc743f288bf72e485fefb3a967b733686 (diff) |
[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 <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/scan.c')
-rw-r--r-- | drivers/net/wireless/libertas/scan.c | 131 |
1 files changed, 77 insertions, 54 deletions
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index b2919a6876e6..437a1e98671f 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -59,6 +59,9 @@ | |||
59 | //! Scan time specified in the channel TLV for each channel for active scans | 59 | //! Scan time specified in the channel TLV for each channel for active scans |
60 | #define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 | 60 | #define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 |
61 | 61 | ||
62 | const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
63 | const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | ||
64 | |||
62 | static inline void clear_bss_descriptor (struct bss_descriptor * bss) | 65 | static inline void clear_bss_descriptor (struct bss_descriptor * bss) |
63 | { | 66 | { |
64 | /* Don't blow away ->list, just BSS data */ | 67 | /* Don't blow away ->list, just BSS data */ |
@@ -409,13 +412,11 @@ wlan_scan_setup_scan_config(wlan_private * priv, | |||
409 | u8 * pscancurrentonly) | 412 | u8 * pscancurrentonly) |
410 | { | 413 | { |
411 | wlan_adapter *adapter = priv->adapter; | 414 | wlan_adapter *adapter = priv->adapter; |
412 | const u8 zeromac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; | ||
413 | struct mrvlietypes_numprobes *pnumprobestlv; | 415 | struct mrvlietypes_numprobes *pnumprobestlv; |
414 | struct mrvlietypes_ssidparamset *pssidtlv; | 416 | struct mrvlietypes_ssidparamset *pssidtlv; |
415 | struct wlan_scan_cmd_config * pscancfgout = NULL; | 417 | struct wlan_scan_cmd_config * pscancfgout = NULL; |
416 | u8 *ptlvpos; | 418 | u8 *ptlvpos; |
417 | u16 numprobes; | 419 | u16 numprobes; |
418 | u16 ssidlen; | ||
419 | int chanidx; | 420 | int chanidx; |
420 | int scantype; | 421 | int scantype; |
421 | int scandur; | 422 | int scandur; |
@@ -472,21 +473,18 @@ wlan_scan_setup_scan_config(wlan_private * priv, | |||
472 | * Set the BSSID filter to the incoming configuration, | 473 | * Set the BSSID filter to the incoming configuration, |
473 | * if non-zero. If not set, it will remain disabled (all zeros). | 474 | * if non-zero. If not set, it will remain disabled (all zeros). |
474 | */ | 475 | */ |
475 | memcpy(pscancfgout->specificBSSID, | 476 | memcpy(pscancfgout->bssid, puserscanin->bssid, |
476 | puserscanin->specificBSSID, | 477 | sizeof(pscancfgout->bssid)); |
477 | sizeof(pscancfgout->specificBSSID)); | ||
478 | |||
479 | ssidlen = strlen(puserscanin->specificSSID); | ||
480 | 478 | ||
481 | if (ssidlen) { | 479 | if (puserscanin->ssid_len) { |
482 | pssidtlv = | 480 | pssidtlv = |
483 | (struct mrvlietypes_ssidparamset *) pscancfgout-> | 481 | (struct mrvlietypes_ssidparamset *) pscancfgout-> |
484 | tlvbuffer; | 482 | tlvbuffer; |
485 | pssidtlv->header.type = cpu_to_le16(TLV_TYPE_SSID); | 483 | pssidtlv->header.type = cpu_to_le16(TLV_TYPE_SSID); |
486 | pssidtlv->header.len = cpu_to_le16(ssidlen); | 484 | pssidtlv->header.len = cpu_to_le16(puserscanin->ssid_len); |
487 | memcpy(pssidtlv->ssid, puserscanin->specificSSID, | 485 | memcpy(pssidtlv->ssid, puserscanin->ssid, |
488 | ssidlen); | 486 | puserscanin->ssid_len); |
489 | ptlvpos += sizeof(pssidtlv->header) + ssidlen; | 487 | ptlvpos += sizeof(pssidtlv->header) + puserscanin->ssid_len; |
490 | } | 488 | } |
491 | 489 | ||
492 | /* | 490 | /* |
@@ -495,8 +493,8 @@ wlan_scan_setup_scan_config(wlan_private * priv, | |||
495 | * scan results. That is not an issue with an SSID or BSSID | 493 | * scan results. That is not an issue with an SSID or BSSID |
496 | * filter applied to the scan results in the firmware. | 494 | * filter applied to the scan results in the firmware. |
497 | */ | 495 | */ |
498 | if (ssidlen || (memcmp(pscancfgout->specificBSSID, | 496 | if ( puserscanin->ssid_len |
499 | &zeromac, sizeof(zeromac)) != 0)) { | 497 | || (compare_ether_addr(pscancfgout->bssid, &zeromac[0]) != 0)) { |
500 | *pmaxchanperscan = MRVDRV_MAX_CHANNELS_PER_SCAN; | 498 | *pmaxchanperscan = MRVDRV_MAX_CHANNELS_PER_SCAN; |
501 | *pfilteredscan = 1; | 499 | *pfilteredscan = 1; |
502 | } | 500 | } |
@@ -743,6 +741,53 @@ done: | |||
743 | return ret; | 741 | return ret; |
744 | } | 742 | } |
745 | 743 | ||
744 | static void | ||
745 | clear_selected_scan_list_entries(wlan_adapter * adapter, | ||
746 | const struct wlan_ioctl_user_scan_cfg * scan_cfg) | ||
747 | { | ||
748 | struct bss_descriptor * bss; | ||
749 | struct bss_descriptor * safe; | ||
750 | u32 clear_ssid_flag = 0, clear_bssid_flag = 0; | ||
751 | |||
752 | if (!scan_cfg) | ||
753 | return; | ||
754 | |||
755 | if (scan_cfg->clear_ssid && scan_cfg->ssid_len) | ||
756 | clear_ssid_flag = 1; | ||
757 | |||
758 | if (scan_cfg->clear_bssid | ||
759 | && (compare_ether_addr(scan_cfg->bssid, &zeromac[0]) != 0) | ||
760 | && (compare_ether_addr(scan_cfg->bssid, &bcastmac[0]) != 0)) { | ||
761 | clear_bssid_flag = 1; | ||
762 | } | ||
763 | |||
764 | if (!clear_ssid_flag && !clear_bssid_flag) | ||
765 | return; | ||
766 | |||
767 | mutex_lock(&adapter->lock); | ||
768 | list_for_each_entry_safe (bss, safe, &adapter->network_list, list) { | ||
769 | u32 clear = 0; | ||
770 | |||
771 | /* Check for an SSID match */ | ||
772 | if ( clear_ssid_flag | ||
773 | && (bss->ssid.ssidlength == scan_cfg->ssid_len) | ||
774 | && !memcmp(bss->ssid.ssid, scan_cfg->ssid, bss->ssid.ssidlength)) | ||
775 | clear = 1; | ||
776 | |||
777 | /* Check for a BSSID match */ | ||
778 | if ( clear_bssid_flag | ||
779 | && !compare_ether_addr(bss->bssid, scan_cfg->bssid)) | ||
780 | clear = 1; | ||
781 | |||
782 | if (clear) { | ||
783 | list_move_tail (&bss->list, &adapter->network_free_list); | ||
784 | clear_bss_descriptor(bss); | ||
785 | } | ||
786 | } | ||
787 | mutex_unlock(&adapter->lock); | ||
788 | } | ||
789 | |||
790 | |||
746 | /** | 791 | /** |
747 | * @brief Internal function used to start a scan based on an input config | 792 | * @brief Internal function used to start a scan based on an input config |
748 | * | 793 | * |
@@ -760,11 +805,10 @@ int wlan_scan_networks(wlan_private * priv, | |||
760 | const struct wlan_ioctl_user_scan_cfg * puserscanin, | 805 | const struct wlan_ioctl_user_scan_cfg * puserscanin, |
761 | int full_scan) | 806 | int full_scan) |
762 | { | 807 | { |
763 | wlan_adapter *adapter = priv->adapter; | 808 | wlan_adapter * adapter = priv->adapter; |
764 | struct mrvlietypes_chanlistparamset *pchantlvout; | 809 | struct mrvlietypes_chanlistparamset *pchantlvout; |
765 | struct chanscanparamset * scan_chan_list = NULL; | 810 | struct chanscanparamset * scan_chan_list = NULL; |
766 | struct wlan_scan_cmd_config * scan_cfg = NULL; | 811 | struct wlan_scan_cmd_config * scan_cfg = NULL; |
767 | u8 keeppreviousscan; | ||
768 | u8 filteredscan; | 812 | u8 filteredscan; |
769 | u8 scancurrentchanonly; | 813 | u8 scancurrentchanonly; |
770 | int maxchanperscan; | 814 | int maxchanperscan; |
@@ -791,28 +835,7 @@ int wlan_scan_networks(wlan_private * priv, | |||
791 | goto out; | 835 | goto out; |
792 | } | 836 | } |
793 | 837 | ||
794 | keeppreviousscan = 0; | 838 | clear_selected_scan_list_entries(adapter, puserscanin); |
795 | |||
796 | if (puserscanin) { | ||
797 | keeppreviousscan = puserscanin->keeppreviousscan; | ||
798 | } | ||
799 | |||
800 | if (adapter->last_scanned_channel) | ||
801 | keeppreviousscan = 1; | ||
802 | |||
803 | if (!keeppreviousscan) { | ||
804 | struct bss_descriptor * iter_bss; | ||
805 | struct bss_descriptor * safe; | ||
806 | |||
807 | mutex_lock(&adapter->lock); | ||
808 | list_for_each_entry_safe (iter_bss, safe, | ||
809 | &adapter->network_list, list) { | ||
810 | list_move_tail (&iter_bss->list, | ||
811 | &adapter->network_free_list); | ||
812 | clear_bss_descriptor(iter_bss); | ||
813 | } | ||
814 | mutex_unlock(&adapter->lock); | ||
815 | } | ||
816 | 839 | ||
817 | /* Keep the data path active if we are only scanning our current channel */ | 840 | /* Keep the data path active if we are only scanning our current channel */ |
818 | if (!scancurrentchanonly) { | 841 | if (!scancurrentchanonly) { |
@@ -1434,30 +1457,30 @@ int libertas_set_scan(struct net_device *dev, struct iw_request_info *info, | |||
1434 | */ | 1457 | */ |
1435 | int libertas_send_specific_SSID_scan(wlan_private * priv, | 1458 | int libertas_send_specific_SSID_scan(wlan_private * priv, |
1436 | struct WLAN_802_11_SSID *prequestedssid, | 1459 | struct WLAN_802_11_SSID *prequestedssid, |
1437 | u8 keeppreviousscan) | 1460 | u8 clear_ssid) |
1438 | { | 1461 | { |
1439 | wlan_adapter *adapter = priv->adapter; | 1462 | wlan_adapter *adapter = priv->adapter; |
1440 | struct wlan_ioctl_user_scan_cfg scancfg; | 1463 | struct wlan_ioctl_user_scan_cfg scancfg; |
1464 | int ret = 0; | ||
1441 | 1465 | ||
1442 | lbs_deb_enter(LBS_DEB_ASSOC); | 1466 | lbs_deb_enter(LBS_DEB_ASSOC); |
1443 | 1467 | ||
1444 | if (prequestedssid == NULL) { | 1468 | if (prequestedssid == NULL) |
1445 | return -1; | 1469 | goto out; |
1446 | } | ||
1447 | 1470 | ||
1448 | memset(&scancfg, 0x00, sizeof(scancfg)); | 1471 | memset(&scancfg, 0x00, sizeof(scancfg)); |
1449 | 1472 | memcpy(scancfg.ssid, prequestedssid->ssid, prequestedssid->ssidlength); | |
1450 | memcpy(scancfg.specificSSID, prequestedssid->ssid, | 1473 | scancfg.ssid_len = prequestedssid->ssidlength; |
1451 | prequestedssid->ssidlength); | 1474 | scancfg.clear_ssid = clear_ssid; |
1452 | scancfg.keeppreviousscan = keeppreviousscan; | ||
1453 | 1475 | ||
1454 | wlan_scan_networks(priv, &scancfg, 1); | 1476 | wlan_scan_networks(priv, &scancfg, 1); |
1455 | if (adapter->surpriseremoved) | 1477 | if (adapter->surpriseremoved) |
1456 | return -1; | 1478 | return -1; |
1457 | wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending); | 1479 | wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending); |
1458 | 1480 | ||
1481 | out: | ||
1459 | lbs_deb_leave(LBS_DEB_ASSOC); | 1482 | lbs_deb_leave(LBS_DEB_ASSOC); |
1460 | return 0; | 1483 | return ret; |
1461 | } | 1484 | } |
1462 | 1485 | ||
1463 | /** | 1486 | /** |
@@ -1469,19 +1492,18 @@ int libertas_send_specific_SSID_scan(wlan_private * priv, | |||
1469 | * | 1492 | * |
1470 | * @return 0-success, otherwise fail | 1493 | * @return 0-success, otherwise fail |
1471 | */ | 1494 | */ |
1472 | int libertas_send_specific_BSSID_scan(wlan_private * priv, u8 * bssid, u8 keeppreviousscan) | 1495 | int libertas_send_specific_BSSID_scan(wlan_private * priv, u8 * bssid, u8 clear_bssid) |
1473 | { | 1496 | { |
1474 | struct wlan_ioctl_user_scan_cfg scancfg; | 1497 | struct wlan_ioctl_user_scan_cfg scancfg; |
1475 | 1498 | ||
1476 | lbs_deb_enter(LBS_DEB_ASSOC); | 1499 | lbs_deb_enter(LBS_DEB_ASSOC); |
1477 | 1500 | ||
1478 | if (bssid == NULL) { | 1501 | if (bssid == NULL) |
1479 | return -1; | 1502 | goto out; |
1480 | } | ||
1481 | 1503 | ||
1482 | memset(&scancfg, 0x00, sizeof(scancfg)); | 1504 | memset(&scancfg, 0x00, sizeof(scancfg)); |
1483 | memcpy(scancfg.specificBSSID, bssid, sizeof(scancfg.specificBSSID)); | 1505 | memcpy(scancfg.bssid, bssid, ETH_ALEN); |
1484 | scancfg.keeppreviousscan = keeppreviousscan; | 1506 | scancfg.clear_bssid = clear_bssid; |
1485 | 1507 | ||
1486 | wlan_scan_networks(priv, &scancfg, 1); | 1508 | wlan_scan_networks(priv, &scancfg, 1); |
1487 | if (priv->adapter->surpriseremoved) | 1509 | if (priv->adapter->surpriseremoved) |
@@ -1489,6 +1511,7 @@ int libertas_send_specific_BSSID_scan(wlan_private * priv, u8 * bssid, u8 keeppr | |||
1489 | wait_event_interruptible(priv->adapter->cmd_pending, | 1511 | wait_event_interruptible(priv->adapter->cmd_pending, |
1490 | !priv->adapter->nr_cmd_pending); | 1512 | !priv->adapter->nr_cmd_pending); |
1491 | 1513 | ||
1514 | out: | ||
1492 | lbs_deb_leave(LBS_DEB_ASSOC); | 1515 | lbs_deb_leave(LBS_DEB_ASSOC); |
1493 | return 0; | 1516 | return 0; |
1494 | } | 1517 | } |
@@ -1727,7 +1750,7 @@ int libertas_cmd_80211_scan(wlan_private * priv, | |||
1727 | 1750 | ||
1728 | /* Set fixed field variables in scan command */ | 1751 | /* Set fixed field variables in scan command */ |
1729 | pscan->bsstype = pscancfg->bsstype; | 1752 | pscan->bsstype = pscancfg->bsstype; |
1730 | memcpy(pscan->BSSID, pscancfg->specificBSSID, sizeof(pscan->BSSID)); | 1753 | memcpy(pscan->BSSID, pscancfg->bssid, sizeof(pscan->BSSID)); |
1731 | memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen); | 1754 | memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen); |
1732 | 1755 | ||
1733 | cmd->command = cpu_to_le16(cmd_802_11_scan); | 1756 | cmd->command = cpu_to_le16(cmd_802_11_scan); |