aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwmc3200wifi/rx.c
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2009-09-01 09:14:02 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-09-01 12:48:27 -0400
commitc7436273889e0ce511b317041f35344e92344885 (patch)
tree6b18a0a3d5308226afac15e1a545ef30119c925a /drivers/net/wireless/iwmc3200wifi/rx.c
parentde15fd31fcabb4b81a556736dd67ec4f71462f07 (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.c32
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
604static 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
592static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf, 615static 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: