diff options
author | Zhu Yi <yi.zhu@intel.com> | 2009-09-01 09:14:02 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-09-01 12:48:27 -0400 |
commit | c7436273889e0ce511b317041f35344e92344885 (patch) | |
tree | 6b18a0a3d5308226afac15e1a545ef30119c925a /drivers/net/wireless/iwmc3200wifi/rx.c | |
parent | de15fd31fcabb4b81a556736dd67ec4f71462f07 (diff) |
iwmc3200wifi: add disconnect work
When the driver receives "connection terminated" event from device,
it could be caused by 2 reasons: the firmware is roaming or the
connection is lost (AP disappears). For the former, an association
complete event is supposed to come within 3 seconds. For the latter,
the driver won't receive any event except the connection terminated.
So we kick a delayed work (5*HZ) when we receive the connection
terminated event. It will be canceled if it turns out to be a roaming
event later. Otherwise we notify SME and userspace the disconnection.
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi/rx.c')
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/rx.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 9e6f2cd38d60..4d9793e68650 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -514,6 +514,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
514 | /* Internal roaming state, avoid notifying SME. */ | 514 | /* Internal roaming state, avoid notifying SME. */ |
515 | if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) | 515 | if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) |
516 | && iwm->conf.mode == UMAC_MODE_BSS) { | 516 | && iwm->conf.mode == UMAC_MODE_BSS) { |
517 | cancel_delayed_work(&iwm->disconnect); | ||
517 | cfg80211_roamed(iwm_to_ndev(iwm), | 518 | cfg80211_roamed(iwm_to_ndev(iwm), |
518 | complete->bssid, | 519 | complete->bssid, |
519 | iwm->req_ie, iwm->req_ie_len, | 520 | iwm->req_ie, iwm->req_ie_len, |
@@ -540,8 +541,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
540 | 541 | ||
541 | /* Internal roaming state, avoid notifying SME. */ | 542 | /* Internal roaming state, avoid notifying SME. */ |
542 | if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) | 543 | if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) |
543 | && iwm->conf.mode == UMAC_MODE_BSS) | 544 | && iwm->conf.mode == UMAC_MODE_BSS) { |
545 | cancel_delayed_work(&iwm->disconnect); | ||
544 | break; | 546 | break; |
547 | } | ||
545 | 548 | ||
546 | iwm_link_off(iwm); | 549 | iwm_link_off(iwm); |
547 | 550 | ||
@@ -569,11 +572,18 @@ static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf, | |||
569 | struct iwm_wifi_cmd *cmd) | 572 | struct iwm_wifi_cmd *cmd) |
570 | { | 573 | { |
571 | struct iwm_umac_notif_profile_invalidate *invalid; | 574 | struct iwm_umac_notif_profile_invalidate *invalid; |
575 | u32 reason; | ||
572 | 576 | ||
573 | invalid = (struct iwm_umac_notif_profile_invalidate *)buf; | 577 | invalid = (struct iwm_umac_notif_profile_invalidate *)buf; |
578 | reason = le32_to_cpu(invalid->reason); | ||
579 | |||
580 | IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n", reason); | ||
574 | 581 | ||
575 | IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n", | 582 | if (reason != UMAC_PROFILE_INVALID_REQUEST && |
576 | le32_to_cpu(invalid->reason)); | 583 | test_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)) |
584 | cfg80211_connect_result(iwm_to_ndev(iwm), NULL, NULL, 0, NULL, | ||
585 | 0, WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
586 | GFP_KERNEL); | ||
577 | 587 | ||
578 | clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status); | 588 | clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status); |
579 | clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); | 589 | clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); |
@@ -589,6 +599,19 @@ static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf, | |||
589 | return 0; | 599 | return 0; |
590 | } | 600 | } |
591 | 601 | ||
602 | #define IWM_DISCONNECT_INTERVAL (5 * HZ) | ||
603 | |||
604 | static int iwm_mlme_connection_terminated(struct iwm_priv *iwm, u8 *buf, | ||
605 | unsigned long buf_size, | ||
606 | struct iwm_wifi_cmd *cmd) | ||
607 | { | ||
608 | IWM_DBG_MLME(iwm, DBG, "Connection terminated\n"); | ||
609 | |||
610 | schedule_delayed_work(&iwm->disconnect, IWM_DISCONNECT_INTERVAL); | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
592 | static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf, | 615 | static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf, |
593 | unsigned long buf_size, | 616 | unsigned long buf_size, |
594 | struct iwm_wifi_cmd *cmd) | 617 | struct iwm_wifi_cmd *cmd) |
@@ -848,8 +871,7 @@ static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf, | |||
848 | case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE: | 871 | case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE: |
849 | return iwm_mlme_profile_invalidate(iwm, buf, buf_size, cmd); | 872 | return iwm_mlme_profile_invalidate(iwm, buf, buf_size, cmd); |
850 | case WIFI_IF_NTFY_CONNECTION_TERMINATED: | 873 | case WIFI_IF_NTFY_CONNECTION_TERMINATED: |
851 | IWM_DBG_MLME(iwm, DBG, "Connection terminated\n"); | 874 | return iwm_mlme_connection_terminated(iwm, buf, buf_size, cmd); |
852 | break; | ||
853 | case WIFI_IF_NTFY_SCAN_COMPLETE: | 875 | case WIFI_IF_NTFY_SCAN_COMPLETE: |
854 | return iwm_mlme_scan_complete(iwm, buf, buf_size, cmd); | 876 | return iwm_mlme_scan_complete(iwm, buf, buf_size, cmd); |
855 | case WIFI_IF_NTFY_STA_TABLE_CHANGE: | 877 | case WIFI_IF_NTFY_STA_TABLE_CHANGE: |